View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.httppart;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.apache.juneau.common.utils.IOUtils.*;
21  import static org.apache.juneau.common.utils.StringUtils.*;
22  import static org.apache.juneau.httppart.HttpPartSchema.*;
23  import static org.junit.jupiter.api.Assertions.*;
24  
25  import java.io.*;
26  import java.lang.reflect.*;
27  import java.util.*;
28  
29  import org.apache.juneau.*;
30  import org.apache.juneau.collections.*;
31  import org.apache.juneau.json.*;
32  import org.apache.juneau.oapi.*;
33  import org.apache.juneau.parser.*;
34  import org.junit.jupiter.api.*;
35  
36  class OpenApiPartParser_Test extends TestBase {
37  
38  	static OpenApiParserSession p = OpenApiParser.DEFAULT.getSession();
39  
40  	private static <T> T parse(HttpPartSchema schema, String input, Class<T> type) throws SchemaValidationException, ParseException {
41  		return p.parse(null, schema, input, p.getClassMeta(type));
42  	}
43  
44  	private static <T> T parse(HttpPartSchema schema, String input, Class<T> type, Type...args) throws SchemaValidationException, ParseException {
45  		return p.parse(null, schema, input, p.getClassMeta(type, args));
46  	}
47  
48  	//-----------------------------------------------------------------------------------------------------------------
49  	// Input validations
50  	//-----------------------------------------------------------------------------------------------------------------
51  
52  	@Test void a01_inputValidations_nullInput() throws Exception {
53  		assertNull(parse(T_NONE, null, String.class));
54  		assertNull(parse(tNone().required(false).build(), null, String.class));
55  		assertThrowsWithMessage(SchemaValidationException.class, "No value specified.", ()->parse(tNone().required().build(), null, String.class));
56  		assertThrowsWithMessage(SchemaValidationException.class, "No value specified.", ()->parse(tNone().required(true).build(), null, String.class));
57  	}
58  
59  	@Test void a02_inputValidations_emptyInput() throws Exception {
60  
61  		var s = tNone().allowEmptyValue().build();
62  		assertEquals("", parse(s, "", String.class));
63  
64  		s = tNone().allowEmptyValue().build();
65  		assertEquals("", parse(s, "", String.class));
66  
67  		assertThrowsWithMessage(SchemaValidationException.class, "Empty value not allowed.", ()->parse(tNone().allowEmptyValue(false).build(), "", String.class));
68  
69  		assertEquals(" ", parse(s, " ", String.class));
70  	}
71  
72  	@Test void a03_inputValidations_pattern() throws Exception {
73  		final HttpPartSchema s = tNone().pattern("x.*").allowEmptyValue().build();
74  		assertEquals("x", parse(s, "x", String.class));
75  		assertEquals("xx", parse(s, "xx", String.class));
76  		assertEquals(null, parse(s, null, String.class));
77  
78  		assertThrowsWithMessage(SchemaValidationException.class, "Value does not match expected pattern.  Must match pattern: x.*", ()->parse(s, "y", String.class));
79  		assertThrowsWithMessage(SchemaValidationException.class, "Value does not match expected pattern.  Must match pattern: x.*", ()->parse(s, "", String.class));
80  
81  		// Blank/null patterns are ignored.
82  		assertEquals("x", parse(tNone().pattern("").allowEmptyValue().build(), "x", String.class));
83  		assertEquals("x", parse(tNone().pattern(null).allowEmptyValue().build(), "x", String.class));
84  	}
85  
86  	@Test void a04_inputValidations_enum() throws Exception {
87  		var s = tNone()._enum("foo").allowEmptyValue().build();
88  
89  		assertEquals("foo", parse(s, "foo", String.class));
90  		assertEquals(null, parse(s, null, String.class));
91  
92  		assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values.  Must be one of the following:  foo", ()->parse(s, "bar", String.class));
93  		assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values.  Must be one of the following:  foo", ()->parse(s, "", String.class));
94  
95  		assertEquals("foo", parse(tNone()._enum((Set<String>)null).build(), "foo", String.class));
96  		assertEquals("foo", parse(tNone()._enum((Set<String>)null).allowEmptyValue().build(), "foo", String.class));
97  		assertEquals("foo", parse(tNone()._enum("foo","foo").build(), "foo", String.class));
98  	}
99  
100 	@Test void a05_inputValidations_minMaxLength() throws Exception {
101 		var s = tNone().minLength(1L).maxLength(2L).allowEmptyValue().build();
102 
103 		assertEquals(null, parse(s, null, String.class));
104 		assertEquals("1", parse(s, "1", String.class));
105 		assertEquals("12", parse(s, "12", String.class));
106 
107 		assertThrowsWithMessage(SchemaValidationException.class, "Minimum length of value not met.", ()->parse(s, "", String.class));
108 		assertThrowsWithMessage(SchemaValidationException.class, "Maximum length of value exceeded.", ()->parse(s, "123", String.class));
109 		assertThrowsWithMessage(Exception.class, "maxLength cannot be less than minLength.", ()->tNone().minLength(2L).maxLength(1L).build());
110 		assertThrowsWithMessage(Exception.class, "minLength cannot be less than zero.", ()->tNone().minLength(-2L).build());
111 		assertThrowsWithMessage(Exception.class, "maxLength cannot be less than zero.", ()->tNone().maxLength(-2L).build());
112 	}
113 
114 	//-----------------------------------------------------------------------------------------------------------------
115 	// Primitive defaults
116 	//-----------------------------------------------------------------------------------------------------------------
117 
118 	@Test void b01_primitiveDefaults() throws Exception {
119 		assertEquals(null, parse(null, null, Boolean.class));
120 		assertEquals(false, parse(null, null, boolean.class));
121 		assertEquals(null, parse(null, null, Character.class));
122 		assertEquals("\0", parse(null, null, char.class).toString());
123 		assertEquals(null, parse(null, null, Short.class));
124 		assertEquals(0, parse(null, null, short.class).intValue());
125 		assertEquals(null, parse(null, null, Integer.class));
126 		assertEquals(0, parse(null, null, int.class).intValue());
127 		assertEquals(null, parse(null, null, Long.class));
128 		assertEquals(0, parse(null, null, long.class).intValue());
129 		assertEquals(null, parse(null, null, Float.class));
130 		assertEquals(0, parse(null, null, float.class).intValue());
131 		assertEquals(null, parse(null, null, Double.class));
132 		assertEquals(0, parse(null, null, double.class).intValue());
133 		assertEquals(null, parse(null, null, Byte.class));
134 		assertEquals(0, parse(null, null, byte.class).intValue());
135 	}
136 
137 	@Test void b02_primitiveDefaults_nullKeyword() throws Exception {
138 		assertEquals(null, parse(null, "null", Boolean.class));
139 		assertEquals(false, parse(null, "null", boolean.class));
140 		assertEquals(null, parse(null, "null", Character.class));
141 		assertEquals("\0", parse(null, "null", char.class).toString());
142 		assertEquals(null, parse(null, "null", Short.class));
143 		assertEquals(0, parse(null, "null", short.class).intValue());
144 		assertEquals(null, parse(null, "null", Integer.class));
145 		assertEquals(0, parse(null, "null", int.class).intValue());
146 		assertEquals(null, parse(null, "null", Long.class));
147 		assertEquals(0, parse(null, "null", long.class).intValue());
148 		assertEquals(null, parse(null, "null", Float.class));
149 		assertEquals(0, parse(null, "null", float.class).intValue());
150 		assertEquals(null, parse(null, "null", Double.class));
151 		assertEquals(0, parse(null, "null", double.class).intValue());
152 		assertEquals(null, parse(null, "null", Byte.class));
153 		assertEquals(0, parse(null, "null", byte.class).intValue());
154 	}
155 
156 	//-----------------------------------------------------------------------------------------------------------------
157 	// type = string
158 	//-----------------------------------------------------------------------------------------------------------------
159 
160 	public static class C1 {
161 		private String f;
162 		public C1(byte[] b) {
163 			f = "C1-" + new String(b);
164 		}
165 		@Override
166 		public String toString() {
167 			return f;
168 		}
169 	}
170 
171 	public static class C2 {
172 		private String f;
173 		public C2(String s) {
174 			f = "C2-" + s;
175 		}
176 		@Override
177 		public String toString() {
178 			return f;
179 		}
180 	}
181 
182 	public static class C3 {
183 		private String f;
184 		public C3(String[] in) {
185 			f = "C3-" + Json5Serializer.DEFAULT.toString(in);
186 		}
187 		@Override
188 		public String toString() {
189 			return f;
190 		}
191 	}
192 
193 
194 	@Test void c01_stringType_simple() throws Exception {
195 		var s = T_STRING;
196 		assertEquals("foo", parse(s, "foo", String.class));
197 	}
198 
199 	@Test void c02_stringType_default() throws Exception {
200 		var s = tString()._default("x").build();
201 		assertEquals("foo", parse(s, "foo", String.class));
202 		assertEquals("x", parse(s, null, String.class));
203 	}
204 
205 	@Test void c03_stringType_byteFormat() throws Exception {
206 		var s = T_BYTE;
207 		var in = base64Encode("foo".getBytes());
208 		assertEquals("foo", parse(s, in, String.class));
209 		assertEquals("foo", read(parse(s, in, InputStream.class)));
210 		assertEquals("foo", read(parse(s, in, Reader.class)));
211 		assertEquals("C1-foo", parse(s, in, C1.class).toString());
212 	}
213 
214 	@Test void c04_stringType_binaryFormat() throws Exception {
215 		var s = T_BINARY;
216 		var in = toHex("foo".getBytes());
217 		assertEquals("foo", parse(s, in, String.class));
218 		assertEquals("foo", read(parse(s, in, InputStream.class)));
219 		assertEquals("foo", read(parse(s, in, Reader.class)));
220 		assertEquals("C1-foo", parse(s, in, C1.class).toString());
221 	}
222 
223 	@Test void c05_stringType_binarySpacedFormat() throws Exception {
224 		var s = T_BINARY_SPACED;
225 		var in = toSpacedHex("foo".getBytes());
226 		assertEquals("foo", parse(s, in, String.class));
227 		assertEquals("foo", read(parse(s, in, InputStream.class)));
228 		assertEquals("foo", read(parse(s, in, Reader.class)));
229 		assertEquals("C1-foo", parse(s, in, C1.class).toString());
230 	}
231 
232 	@Test void c06_stringType_dateFormat() throws Exception {
233 		var s = T_DATE;
234 		var in = "2012-12-21";
235 		assertTrue(parse(s, in, String.class).contains("2012"));
236 		assertTrue(parse(s, in, Date.class).toString().contains("2012"));
237 		assertEquals(2012, parse(s, in, Calendar.class).get(Calendar.YEAR));
238 		assertEquals(2012, parse(s, in, GregorianCalendar.class).get(Calendar.YEAR));
239 	}
240 
241 	@Test void c07_stringType_dateTimeFormat() throws Exception {
242 		var s = T_DATETIME;
243 		var in = "2012-12-21T12:34:56.789";
244 		assertTrue(parse(s, in, String.class).contains("2012"));
245 		assertTrue(parse(s, in, Date.class).toString().contains("2012"));
246 		assertEquals(2012, parse(s, in, Calendar.class).get(Calendar.YEAR));
247 		assertEquals(2012, parse(s, in, GregorianCalendar.class).get(Calendar.YEAR));
248 	}
249 
250 	@Test void c08_stringType_uonFormat() throws Exception {
251 		var s = T_UON;
252 		assertEquals("foo", parse(s, "foo", String.class));
253 		assertEquals("foo", parse(s, "'foo'", String.class));
254 		assertEquals("C2-foo", parse(s, "'foo'", C2.class).toString());
255 		// UonPartParserTest should handle all other cases.
256 	}
257 
258 	@Test void c09_stringType_noneFormat() throws Exception {
259 		// If no format is specified, then we should transform directly from a string.
260 		var s = T_STRING;
261 		assertEquals("foo", parse(s, "foo", String.class));
262 		assertEquals("'foo'", parse(s, "'foo'", String.class));
263 		assertEquals("C2-foo", parse(s, "foo", C2.class).toString());
264 	}
265 
266 	@Test void c10_stringType_noneFormat_2d() throws Exception {
267 		var s = tArray(tString()).build();
268 		assertList(parse(s, "foo,bar", String[].class), "foo", "bar");
269 		assertList(parse(s, "foo,bar", List.class, String.class), "foo", "bar");
270 		assertList(parse(s, "foo,bar", Object[].class), "foo", "bar");
271 		assertList(parse(s, "foo,bar", List.class, Object.class), "foo", "bar");
272 		var o = parse(s, "foo,bar", Object.class);
273 		assertList(o, "foo", "bar");
274 		assertInstanceOf(JsonList.class, o);
275 		assertList(parse(s, "foo,bar", C2[].class), "C2-foo", "C2-bar");
276 		assertList(parse(s, "foo,bar", List.class, C2.class), "C2-foo", "C2-bar");
277 		assertEquals("C3-['foo','bar']", parse(s, "foo,bar", C3.class).toString());
278 	}
279 
280 	@Test void c11_stringType_noneFormat_3d() throws Exception {
281 		var s = tArrayPipes(tArray(tString())).build();
282 		assertList(parse(s, "foo,bar|baz", String[][].class), "[foo,bar]", "[baz]");
283 		assertList(parse(s, "foo,bar|baz", List.class, String[].class), "[foo,bar]", "[baz]");
284 		assertList(parse(s, "foo,bar|baz", List.class, List.class, String.class), "[foo,bar]", "[baz]");
285 		assertList(parse(s, "foo,bar|baz", Object[][].class), "[foo,bar]", "[baz]");
286 		assertList(parse(s, "foo,bar|baz", List.class, Object[].class), "[foo,bar]", "[baz]");
287 		assertList(parse(s, "foo,bar|baz", List.class, List.class, Object.class), "[foo,bar]", "[baz]");
288 		var o = parse(s, "foo,bar|baz", Object.class);
289 		assertList(o, "[foo,bar]", "[baz]");
290 		assertInstanceOf(JsonList.class, o);
291 		assertList(parse(s, "foo,bar|baz", C2[][].class), "[C2-foo,C2-bar]", "[C2-baz]");
292 		assertList(parse(s, "foo,bar|baz", List.class, C2[].class), "[C2-foo,C2-bar]", "[C2-baz]");
293 		assertList(parse(s, "foo,bar|baz", List.class, List.class, C2.class), "[C2-foo,C2-bar]", "[C2-baz]");
294 		assertList(parse(s, "foo,bar|baz", C3[].class), "C3-['foo','bar']", "C3-['baz']");
295 		assertList(parse(s, "foo,bar|baz", List.class, C3.class), "C3-['foo','bar']", "C3-['baz']");
296 	}
297 
298 	@Test void c12a_stringType_nullKeyword_plain() throws Exception {
299 		var s = T_STRING;
300 		assertEquals(null, parse(s, "null", String.class));
301 	}
302 
303 	@Test void c12b_stringType_nullKeyword_plain_2d() throws Exception {
304 		var s = tArray(tString()).build();
305 		assertNull(parse(s, "null", String[].class));
306 		assertList(parse(s, "@(null)", String[].class), (String) null);
307 	}
308 
309 	@Test void c12c_stringType_nullKeyword_uon() throws Exception {
310 		var s = T_UON;
311 		assertNull(parse(s, "null", String.class));
312 		assertEquals("null", parse(s, "'null'", String.class));
313 	}
314 
315 	@Test void c12d_stringType_nullKeyword_uon_2d() throws Exception {
316 		var s = tArray(tUon()).build();
317 		assertList(parse(s, "null,x", String[].class), null, "x");
318 		assertNull(parse(s, "null", String[].class));
319 		assertList(parse(s, "@(null)", String[].class), (String) null);
320 		assertList(parse(s, "'null'", String[].class), "null");
321 		assertList(parse(s, "@('null')", String[].class), "null");
322 	}
323 
324 	//-----------------------------------------------------------------------------------------------------------------
325 	// type = array
326 	//-----------------------------------------------------------------------------------------------------------------
327 
328 	public static class D {
329 		private String f;
330 		public D(String in) {
331 			this.f = "D-" + in;
332 		}
333 		@Override
334 		public String toString() {
335 			return f;
336 		}
337 	}
338 
339 	@Test void d01_arrayType_collectionFormatCsv() throws Exception {
340 		var s = T_ARRAY_CSV;
341 		assertList(parse(s, "foo,bar", String[].class), "foo", "bar");
342 		assertList(parse(s, "foo,bar", Object[].class), "foo", "bar");
343 		assertList(parse(s, "foo,bar", D[].class), "D-foo", "D-bar");
344 		assertList(parse(s, "foo,bar", List.class, String.class), "foo", "bar");
345 		assertList(parse(s, "foo,bar", List.class, Object.class), "foo", "bar");
346 		assertList(parse(s, "foo,bar", List.class, D.class), "D-foo", "D-bar");
347 		assertList(parse(s, "foo,bar", Object.class), "foo", "bar");
348 		assertList(parse(s, "foo,bar", JsonList.class), "foo", "bar");
349 	}
350 
351 	@Test void d02_arrayType_collectionFormatPipes() throws Exception {
352 		var s = T_ARRAY_PIPES;
353 		assertList(parse(s, "foo|bar", String[].class), "foo", "bar");
354 		assertList(parse(s, "foo|bar", Object[].class), "foo", "bar");
355 		assertList(parse(s, "foo|bar", D[].class), "D-foo", "D-bar");
356 		assertList(parse(s, "foo|bar", List.class, String.class), "foo", "bar");
357 		assertList(parse(s, "foo|bar", List.class, Object.class), "foo", "bar");
358 		assertList(parse(s, "foo|bar", List.class, D.class), "D-foo", "D-bar");
359 		assertList(parse(s, "foo|bar", Object.class), "foo", "bar");
360 		assertList(parse(s, "foo|bar", JsonList.class), "foo", "bar");
361 	}
362 
363 	@Test void d03_arrayType_collectionFormatSsv() throws Exception {
364 		var s = T_ARRAY_SSV;
365 		assertList(parse(s, "foo bar", String[].class), "foo", "bar");
366 		assertList(parse(s, "foo bar", Object[].class), "foo", "bar");
367 		assertList(parse(s, "foo bar", D[].class), "D-foo", "D-bar");
368 		assertList(parse(s, "foo bar", List.class, String.class), "foo", "bar");
369 		assertList(parse(s, "foo bar", List.class, Object.class), "foo", "bar");
370 		assertList(parse(s, "foo bar", List.class, D.class), "D-foo", "D-bar");
371 		assertList(parse(s, "foo bar", Object.class), "foo", "bar");
372 		assertList(parse(s, "foo bar", JsonList.class), "foo", "bar");
373 	}
374 
375 	@Test void d04_arrayType_collectionFormatTsv() throws Exception {
376 		var s = T_ARRAY_TSV;
377 		assertList(parse(s, "foo\tbar", String[].class), "foo", "bar");
378 		assertList(parse(s, "foo\tbar", Object[].class), "foo", "bar");
379 		assertList(parse(s, "foo\tbar", D[].class), "D-foo", "D-bar");
380 		assertList(parse(s, "foo\tbar", List.class, String.class), "foo", "bar");
381 		assertList(parse(s, "foo\tbar", List.class, Object.class), "foo", "bar");
382 		assertList(parse(s, "foo\tbar", List.class, D.class), "D-foo", "D-bar");
383 		assertList(parse(s, "foo\tbar", Object.class), "foo", "bar");
384 		assertList(parse(s, "foo\tbar", JsonList.class), "foo", "bar");
385 	}
386 
387 	@Test void d05_arrayType_collectionFormatUon() throws Exception {
388 		var s = T_ARRAY_UON;
389 		assertList(parse(s, "@(foo,bar)", String[].class), "foo", "bar");
390 		assertList(parse(s, "@(foo,bar)", Object[].class), "foo", "bar");
391 		assertList(parse(s, "@(foo,bar)", D[].class), "D-foo", "D-bar");
392 		assertList(parse(s, "@(foo,bar)", List.class, String.class), "foo", "bar");
393 		assertList(parse(s, "@(foo,bar)", List.class, Object.class), "foo", "bar");
394 		assertList(parse(s, "@(foo,bar)", List.class, D.class), "D-foo", "D-bar");
395 		assertList(parse(s, "@(foo,bar)", Object.class), "foo", "bar");
396 		assertList(parse(s, "@(foo,bar)", JsonList.class), "foo", "bar");
397 	}
398 
399 	@Test void d06a_arrayType_collectionFormatNone() throws Exception {
400 		var s = T_ARRAY;
401 		assertList(parse(s, "foo,bar", String[].class), "foo", "bar");
402 		assertList(parse(s, "foo,bar", Object[].class), "foo", "bar");
403 		assertList(parse(s, "foo,bar", D[].class), "D-foo", "D-bar");
404 		assertList(parse(s, "foo,bar", List.class, String.class), "foo", "bar");
405 		assertList(parse(s, "foo,bar", List.class, Object.class), "foo", "bar");
406 		assertList(parse(s, "foo,bar", List.class, D.class), "D-foo", "D-bar");
407 		assertList(parse(s, "foo,bar", Object.class), "foo", "bar");
408 	}
409 
410 	@Test void d06b_arrayType_collectionFormatNone_autoDetectUon() throws Exception {
411 		var s = T_ARRAY;
412 		assertJson("['foo','bar']", parse(s, "@(foo,bar)", String[].class));
413 		assertJson("['foo','bar']", parse(s, "@(foo,bar)", Object[].class));
414 		assertJson("['D-foo','D-bar']", parse(s, "@(foo,bar)", D[].class));
415 		assertJson("['foo','bar']", parse(s, "@(foo,bar)", List.class, String.class));
416 		assertJson("['foo','bar']", parse(s, "@(foo,bar)", List.class, Object.class));
417 		assertJson("['D-foo','D-bar']", parse(s, "@(foo,bar)", List.class, D.class));
418 		assertJson("['foo','bar']", parse(s, "@(foo,bar)", Object.class));
419 	}
420 
421 	@Test void d07_arrayType_collectionFormatMulti() throws Exception {
422 		// collectionFormat=multi should not do any sort of splitting.
423 		var s = T_ARRAY_MULTI;
424 		assertList(parse(s, "foo,bar", String[].class), "foo,bar");
425 		assertList(parse(s, "foo,bar", Object[].class), "foo,bar");
426 		assertList(parse(s, "foo,bar", D[].class), "D-foo,bar");
427 		assertList(parse(s, "foo,bar", List.class, String.class), "foo,bar");
428 		assertList(parse(s, "foo,bar", List.class, Object.class), "foo,bar");
429 		assertList(parse(s, "foo,bar", List.class, D.class), "D-foo,bar");
430 		assertList(parse(s, "foo,bar", Object.class), "foo,bar");
431 	}
432 
433 	@Test void d08_arrayType_collectionFormatCsvAndPipes() throws Exception {
434 		var s = tArrayPipes(tArrayCsv()).build();
435 		assertJson("[['foo','bar'],['baz','qux']]", parse(s, "foo,bar|baz,qux", String[][].class));
436 		assertJson("[['foo','bar'],['baz','qux']]", parse(s, "foo,bar|baz,qux", Object[][].class));
437 		assertJson("[['D-foo','D-bar'],['D-baz','D-qux']]", parse(s, "foo,bar|baz,qux", D[][].class));
438 		assertJson("[['foo','bar'],['baz','qux']]", parse(s, "foo,bar|baz,qux", List.class, List.class, String.class));
439 		assertJson("[['foo','bar'],['baz','qux']]", parse(s, "foo,bar|baz,qux", List.class, List.class, Object.class));
440 		assertJson("[['D-foo','D-bar'],['D-baz','D-qux']]", parse(s, "foo,bar|baz,qux", List.class, List.class, D.class));
441 		assertJson("[['foo','bar'],['baz','qux']]", parse(s, "foo,bar|baz,qux", Object.class));
442 	}
443 
444 	@Test void d09_arrayType_itemsBoolean() throws Exception {
445 		var s = tArrayCsv(tBoolean()).build();
446 		assertList(parse(s, "true,false", boolean[].class), true, false);
447 		assertList(parse(s, "true,false,null", Boolean[].class), true, false, null);
448 		assertList(parse(s, "true,false,null", Object[].class), true, false, null);
449 		assertList(parse(s, "true,false,null", List.class, Boolean.class), true, false, null);
450 		assertList(parse(s, "true,false,null", List.class, Object.class), true, false, null);
451 		assertList(parse(s, "true,false,null", Object.class), true, false, null);
452 	}
453 
454 	@Test void d10_arrayType_itemsInteger() throws Exception {
455 		var s = tArrayCsv(tInteger()).build();
456 		assertList(parse(s, "1,2", int[].class), 1, 2);
457 		assertList(parse(s, "1,2,null", Integer[].class), 1, 2, null);
458 		assertList(parse(s, "1,2,null", Object[].class), 1, 2, null);
459 		assertList(parse(s, "1,2,null", List.class, Integer.class), 1, 2, null);
460 		assertList(parse(s, "1,2,null", List.class, Object.class), 1, 2, null);
461 		assertList(parse(s, "1,2,null", Object.class), 1, 2, null);
462 	}
463 
464 	@Test void d11_arrayType_itemsFloat() throws Exception {
465 		var s = tArrayCsv(tNumber()).build();
466 		assertList(parse(s, "1.0,2.0", float[].class), 1.0f, 2.0f);
467 		assertList(parse(s, "1.0,2.0,null", Float[].class), 1.0f, 2.0f, null);
468 		assertList(parse(s, "1.0,2.0,null", Object[].class), 1.0f, 2.0f, null);
469 		assertList(parse(s, "1.0,2.0,null", List.class, Float.class), 1.0f, 2.0f, null);
470 		assertList(parse(s, "1.0,2.0,null", List.class, Object.class), 1.0f, 2.0f, null);
471 		assertList(parse(s, "1.0,2.0,null", Object.class), 1.0f, 2.0f, null);
472 	}
473 
474 	//-----------------------------------------------------------------------------------------------------------------
475 	// type = boolean
476 	//-----------------------------------------------------------------------------------------------------------------
477 
478 	public static class E1 {
479 		private String f;
480 		public E1(Boolean in) {
481 			this.f = "E1-" + in.toString();
482 		}
483 		@Override
484 		public String toString() {
485 			return f;
486 		}
487 	}
488 
489 	public static class E2 {
490 		private String f;
491 		public E2(Boolean[] in) {
492 			this.f = "E2-" + Json5Serializer.DEFAULT.toString(in);
493 		}
494 		@Override
495 		public String toString() {
496 			return f;
497 		}
498 	}
499 
500 	@Test void e01_booleanType() throws Exception {
501 		var s = T_BOOLEAN;
502 		assertEquals(true, parse(s, "true", boolean.class));
503 		assertEquals(true, parse(s, "true", Boolean.class));
504 		assertNull(parse(s, "null", Boolean.class));
505 		assertEquals(true, parse(s, "True", boolean.class));
506 		assertEquals(true, parse(s, "TRUE", boolean.class));
507 		assertEquals("true", parse(s, "true", String.class));
508 		assertNull(parse(s, "null", String.class));
509 		assertEquals(true, parse(s, "true", Object.class));
510 		assertNull(parse(s, "null", Object.class));
511 		assertJson("'E1-true'", parse(s, "true", E1.class));
512 		assertNull(parse(s, "null", E1.class));
513 	}
514 
515 	@Test void e02_booleanType_2d() throws Exception {
516 		var s = tArray(tBoolean()).build();
517 		assertList(parse(s, "true,true", boolean[].class), true, true);
518 		assertList(parse(s, "true,true,null", Boolean[].class), true, true, null);
519 		assertList(parse(s, "true,true,null", List.class, Boolean.class), true, true, null);
520 		assertList(parse(s, "true,true,null", String[].class), "true", "true", null);
521 		assertList(parse(s, "true,true,null", List.class, String.class), "true", "true", null);
522 		assertList(parse(s, "true,true,null", Object[].class), true, true, null);
523 		assertList(parse(s, "true,true,null", List.class, Object.class), true, true, null);
524 		assertList(parse(s, "true,true,null", E1[].class), "E1-true", "E1-true", null);
525 		assertList(parse(s, "true,true,null", List.class, E1.class), "E1-true", "E1-true", null);
526 		assertJson("'E2-[true,true,null]'", parse(s, "true,true,null", E2.class));
527 
528 		assertList(parse(s, "True,true", boolean[].class), true, true);
529 		assertList(parse(s, "TRUE,true", boolean[].class), true, true);
530 	}
531 
532 	@Test void e03_booleanType_3d() throws Exception {
533 		var s = tArrayPipes(tArray(tBoolean())).build();
534 		assertJson("[[true,true],[false]]", parse(s, "true,true|false", boolean[][].class));
535 		assertJson("[[true,true],[false]]", parse(s, "true,true|false", List.class, boolean[].class));
536 		assertJson("[[true,true],[false,null]]", parse(s, "true,true|false,null", Boolean[][].class));
537 		assertJson("[[true,true],[false,null]]", parse(s, "true,true|false,null", List.class, Boolean[].class));
538 		assertJson("[[true,true],[false,null]]", parse(s, "true,true|false,null", List.class, List.class, Boolean.class));
539 		assertJson("[['true','true'],['false',null]]", parse(s, "true,true|false,null", String[][].class));
540 		assertJson("[['true','true'],['false',null]]", parse(s, "true,true|false,null", List.class, List.class, String.class));
541 		assertJson("[['true','true'],['false',null]]", parse(s, "true,true|false,null", List.class, String[].class));
542 		assertJson("[[true,true],[false,null]]", parse(s, "true,true|false,null", Object[][].class));
543 		assertJson("[[true,true],[false,null]]", parse(s, "true,true|false,null", List.class, List.class, Object.class));
544 		assertJson("[[true,true],[false,null]]", parse(s, "true,true|false,null", List.class, Object[].class));
545 		assertJson("[['E1-true','E1-true'],['E1-false',null]]", parse(s, "true,true|false,null", E1[][].class));
546 		assertJson("[['E1-true','E1-true'],['E1-false',null]]", parse(s, "true,true|false,null", List.class, List.class, E1.class));
547 		assertJson("[['E1-true','E1-true'],['E1-false',null]]", parse(s, "true,true|false,null", List.class, E1[].class));
548 		assertJson("['E2-[true,true]','E2-[false,null]']", parse(s, "true,true|false,null", E2[].class));
549 		assertJson("['E2-[true,true]','E2-[false,null]']", parse(s, "true,true|false,null", List.class, E2.class));
550 
551 		assertJson("[[true,true],[false]]", parse(s, "True,true|false", boolean[][].class));
552 		assertJson("[[true,true],[false]]", parse(s, "TRUE,true|false", boolean[][].class));
553 	}
554 
555 	//-----------------------------------------------------------------------------------------------------------------
556 	// type = integer
557 	//-----------------------------------------------------------------------------------------------------------------
558 
559 	public static class F1 {
560 		private String f;
561 		public F1(Integer in) {
562 			this.f = "F1-" + in.toString();
563 		}
564 		@Override
565 		public String toString() {
566 			return f;
567 		}
568 	}
569 
570 	public static class F2 {
571 		private String f;
572 		public F2(Integer[] in) {
573 			this.f = "F2-" + Json5Serializer.DEFAULT.toString(in);
574 		}
575 		@Override
576 		public String toString() {
577 			return f;
578 		}
579 	}
580 
581 	public static class F3 {
582 		private Long f;
583 		public F3(Long in) {
584 			this.f = in;
585 		}
586 		public Long toLong() {
587 			return f;
588 		}
589 	}
590 
591 	public static class F4 {
592 		private String f;
593 		public F4(Long[] in) {
594 			this.f = "F4-" + Json5Serializer.DEFAULT.toString(in);
595 		}
596 		@Override
597 		public String toString() {
598 			return f;
599 		}
600 	}
601 
602 	@Test void f01_integerType_int32() throws Exception {
603 		var s = T_INT32;
604 		assertJson("1", parse(s, "1", int.class));
605 		assertJson("1", parse(s, "1", Integer.class));
606 		assertJson("1", parse(s, "1", short.class));
607 		assertJson("1", parse(s, "1", Short.class));
608 		assertJson("1", parse(s, "1", long.class));
609 		assertJson("1", parse(s, "1", Long.class));
610 		assertJson("'1'", parse(s, "1", String.class));
611 		var o = parse(s, "1", Object.class);
612 		assertEquals(1, o);
613 		assertInstanceOf(Integer.class, o);
614 		assertJson("'F1-1'", parse(s,  "1", F1.class));
615 	}
616 
617 	@Test void f02_integerType_int32_2d() throws Exception {
618 		var s = tArray(tInt32()).build();
619 		assertList(parse(s, "1,2", int[].class), 1, 2);
620 		assertList(parse(s, "1,2", Integer[].class), 1, 2);
621 		assertList(parse(s, "1,2", List.class, Integer.class), 1, 2);
622 		assertList(parse(s, "1,2", short[].class), (short)1, (short)2);
623 		assertList(parse(s, "1,2", Short[].class), (short)1, (short)2);
624 		assertList(parse(s, "1,2", List.class, Short.class), (short)1, (short)2);
625 		assertList(parse(s, "1,2", long[].class), 1l, 2l);
626 		assertList(parse(s, "1,2", Long[].class), 1l, 2l);
627 		assertList(parse(s, "1,2", List.class, Long.class), 1l, 2l);
628 		assertList(parse(s, "1,2", String[].class), "1", "2");
629 		assertList(parse(s, "1,2", List.class, String.class), "1", "2");
630 		assertList(parse(s, "1,2", Object[].class), 1, 2);
631 		assertList(parse(s, "1,2", List.class, Object.class), 1, 2);
632 		assertList(parse(s,  "1,2", F1[].class), "F1-1", "F1-2");
633 		assertList(parse(s,  "1,2", List.class, F1.class), "F1-1", "F1-2");
634 		assertJson("'F2-[1,2]'", parse(s,  "1,2", F2.class));
635 	}
636 
637 	@Test void f03_integerType_int32_3d() throws Exception {
638 		var s = tArrayPipes(tArray(tInt32())).build();
639 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", int[][].class));
640 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, int[].class));
641 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Integer[][].class));
642 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Integer[].class));
643 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Integer.class));
644 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", short[][].class));
645 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, short[].class));
646 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Short[][].class));
647 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Short[].class));
648 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Short.class));
649 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", long[][].class));
650 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, long[].class));
651 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Long[][].class));
652 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Long[].class));
653 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Long.class));
654 		assertJson("[['1','2'],['3']]", parse(s, "1,2|3", String[][].class));
655 		assertJson("[['1','2'],['3']]", parse(s, "1,2|3", List.class, String[].class));
656 		assertJson("[['1','2'],['3']]", parse(s, "1,2|3", List.class, List.class, String.class));
657 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Object[][].class));
658 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Object[].class));
659 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Object.class));
660 		assertJson("[['F1-1','F1-2'],['F1-3']]", parse(s,  "1,2|3", F1[][].class));
661 		assertJson("[['F1-1','F1-2'],['F1-3']]", parse(s,  "1,2|3", List.class, F1[].class));
662 		assertJson("[['F1-1','F1-2'],['F1-3']]", parse(s,  "1,2|3", List.class, List.class, F1.class));
663 		assertJson("['F2-[1,2]','F2-[3]']", parse(s, "1,2|3", F2[].class));
664 		assertJson("['F2-[1,2]','F2-[3]']", parse(s, "1,2|3", List.class, F2.class));
665 	}
666 
667 	@Test void f04_integerType_int64() throws Exception {
668 		var s = T_INT64;
669 		assertJson("1", parse(s, "1", int.class));
670 		assertJson("1", parse(s, "1", Integer.class));
671 		assertJson("1", parse(s, "1", short.class));
672 		assertJson("1", parse(s, "1", Short.class));
673 		assertJson("1", parse(s, "1", long.class));
674 		assertJson("1", parse(s, "1", Long.class));
675 		assertJson("'1'", parse(s, "1", String.class));
676 		var o = parse(s, "1", Object.class);
677 		assertString("1", o);
678 		assertInstanceOf(Long.class, o);
679 		assertJson("1", parse(s,  "1", F3.class));
680 	}
681 
682 	@Test void f05_integerType_int64_2d() throws Exception {
683 		var s = tArray(tInt64()).build();
684 		assertList(parse(s, "1,2", int[].class), 1, 2);
685 		assertList(parse(s, "1,2", Integer[].class), 1, 2);
686 		assertList(parse(s, "1,2", List.class, Integer.class), 1, 2);
687 		assertList(parse(s, "1,2", short[].class), (short)1, (short)2);
688 		assertList(parse(s, "1,2", Short[].class), (short)1, (short)2);
689 		assertList(parse(s, "1,2", List.class, Short.class), (short)1, (short)2);
690 		assertList(parse(s, "1,2", long[].class), 1l, 2l);
691 		assertList(parse(s, "1,2", Long[].class), 1l, 2l);
692 		assertList(parse(s, "1,2", List.class, Long.class), 1l, 2l);
693 		assertList(parse(s, "1,2", String[].class), "1", "2");
694 		assertList(parse(s, "1,2", List.class, String.class), "1", "2");
695 		assertList(parse(s, "1,2", Object[].class), "1", "2");
696 		assertList(parse(s, "1,2", List.class, Object.class), "1", "2");
697 		assertBeans(parse(s,  "1,2", F3[].class), "f", "1", "2");
698 		assertBeans(parse(s,  "1,2", List.class, F3.class), "f", "1", "2");
699 		assertJson("'F4-[1,2]'", parse(s,  "1,2", F4.class));
700 	}
701 
702 	@Test void f06_integerType_int64_3d() throws Exception {
703 		var s = tArrayPipes(tArray(tInt64())).build();
704 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", int[][].class));
705 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, int[].class));
706 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Integer[][].class));
707 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Integer[].class));
708 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Integer.class));
709 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", short[][].class));
710 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, short[].class));
711 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Short[][].class));
712 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Short[].class));
713 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Short.class));
714 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", long[][].class));
715 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, long[].class));
716 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Long[][].class));
717 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Long[].class));
718 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Long.class));
719 		assertJson("[['1','2'],['3']]", parse(s, "1,2|3", String[][].class));
720 		assertJson("[['1','2'],['3']]", parse(s, "1,2|3", List.class, String[].class));
721 		assertJson("[['1','2'],['3']]", parse(s, "1,2|3", List.class, List.class, String.class));
722 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", Object[][].class));
723 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, Object[].class));
724 		assertJson("[[1,2],[3]]", parse(s, "1,2|3", List.class, List.class, Object.class));
725 		assertJson("[[1,2],[3]]", parse(s,  "1,2|3", F3[][].class));
726 		assertJson("[[1,2],[3]]", parse(s,  "1,2|3", List.class, F3[].class));
727 		assertJson("[[1,2],[3]]", parse(s,  "1,2|3", List.class, List.class, F3.class));
728 		assertJson("['F4-[1,2]','F4-[3]']", parse(s, "1,2|3", F4[].class));
729 		assertJson("['F4-[1,2]','F4-[3]']", parse(s, "1,2|3", List.class, F4.class));
730 	}
731 
732 
733 	//-----------------------------------------------------------------------------------------------------------------
734 	// type = number
735 	//-----------------------------------------------------------------------------------------------------------------
736 
737 	public static class G1 {
738 		private float f;
739 		public G1(float in) {
740 			this.f = in;
741 		}
742 		public float toFloat() {
743 			return f;
744 		}
745 	}
746 
747 	public static class G2 {
748 		private String f;
749 		public G2(Float[] in) {
750 			this.f = "G2-" + Json5Serializer.DEFAULT.toString(in);
751 		}
752 		@Override
753 		public String toString() {
754 			return f;
755 		}
756 	}
757 
758 	public static class G3 {
759 		private Double f;
760 		public G3(double in) {
761 			this.f = in;
762 		}
763 		public double toDouble() {
764 			return f;
765 		}
766 	}
767 
768 	public static class G4 {
769 		private String f;
770 		public G4(Double[] in) {
771 			this.f = "G4-" + Json5Serializer.DEFAULT.toString(in);
772 		}
773 		@Override
774 		public String toString() {
775 			return f;
776 		}
777 	}
778 
779 	@Test void g01_numberType_float() throws Exception {
780 		var s = T_FLOAT;
781 		assertJson("1.0", parse(s, "1", float.class));
782 		assertJson("1.0", parse(s, "1", Float.class));
783 		assertJson("1.0", parse(s, "1", double.class));
784 		assertJson("1.0", parse(s, "1", Double.class));
785 		assertJson("'1.0'", parse(s, "1", String.class));
786 		var o = parse(s, "1", Object.class);
787 		assertEquals(1.0f, o);
788 		assertInstanceOf(Float.class, o);
789 		assertJson("1.0", parse(s,  "1", G1.class));
790 	}
791 
792 	@Test void g02_numberType_float_2d() throws Exception {
793 		var s = tArray(tFloat()).build();
794 		assertList(parse(s, "1,2", float[].class), 1.0f, 2.0f);
795 		assertList(parse(s, "1,2", Float[].class), 1.0f, 2.0f);
796 		assertList(parse(s, "1,2", List.class, Float.class), 1.0f, 2.0f);
797 		assertList(parse(s, "1,2", double[].class), 1.0, 2.0);
798 		assertList(parse(s, "1,2", Double[].class), 1.0, 2.0);
799 		assertList(parse(s, "1,2", List.class, Double.class), 1.0, 2.0);
800 		assertList(parse(s, "1,2", String[].class), "1.0", "2.0");
801 		assertList(parse(s, "1,2", List.class, String.class), "1.0", "2.0");
802 		assertList(parse(s, "1,2", Object[].class), 1.0f, 2.0f);
803 		assertList(parse(s, "1,2", List.class, Object.class), 1.0f, 2.0f);
804 		assertBeans(parse(s,  "1,2", G1[].class), "f", "1.0", "2.0");
805 		assertBeans(parse(s,  "1,2", List.class, G1.class), "f", "1.0", "2.0");
806 		assertJson("'G2-[1.0,2.0]'", parse(s,  "1,2", G2.class));
807 	}
808 
809 	@Test void g03_numberType_float_3d() throws Exception {
810 		var s = tArrayPipes(tArray(tFloat())).build();
811 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", float[][].class));
812 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, float[].class));
813 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", Float[][].class));
814 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, Float[].class));
815 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, List.class, Float.class));
816 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", double[][].class));
817 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, double[].class));
818 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", Double[][].class));
819 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, Double[].class));
820 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, List.class, Double.class));
821 		assertJson("[['1.0','2.0'],['3.0']]", parse(s, "1,2|3", String[][].class));
822 		assertJson("[['1.0','2.0'],['3.0']]", parse(s, "1,2|3", List.class, String[].class));
823 		assertJson("[['1.0','2.0'],['3.0']]", parse(s, "1,2|3", List.class, List.class, String.class));
824 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", Object[][].class));
825 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, Object[].class));
826 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, List.class, Object.class));
827 		assertJson("[[1.0,2.0],[3.0]]", parse(s,  "1,2|3", G1[][].class));
828 		assertJson("[[1.0,2.0],[3.0]]", parse(s,  "1,2|3", List.class, G1[].class));
829 		assertJson("[[1.0,2.0],[3.0]]", parse(s,  "1,2|3", List.class, List.class, G1.class));
830 		assertJson("['G2-[1.0,2.0]','G2-[3.0]']", parse(s, "1,2|3", G2[].class));
831 		assertJson("['G2-[1.0,2.0]','G2-[3.0]']", parse(s, "1,2|3", List.class, G2.class));
832 	}
833 
834 	@Test void g04_numberType_double() throws Exception {
835 		var s = T_DOUBLE;
836 		assertJson("1.0", parse(s, "1", float.class));
837 		assertJson("1.0", parse(s, "1", Float.class));
838 		assertJson("1.0", parse(s, "1", double.class));
839 		assertJson("1.0", parse(s, "1", Double.class));
840 		assertJson("'1.0'", parse(s, "1", String.class));
841 		var o = parse(s, "1", Object.class);
842 		assertString("1.0", o);
843 		assertInstanceOf(Double.class, o);
844 		assertJson("1.0", parse(s,  "1", G3.class));
845 	}
846 
847 	@Test void g05_numberType_double_2d() throws Exception {
848 		var s = tArray(tDouble()).build();
849 		assertList(parse(s, "1,2", float[].class), 1.0f, 2.0f);
850 		assertList(parse(s, "1,2", Float[].class), 1.0f, 2.0f);
851 		assertList(parse(s, "1,2", List.class, Float.class), 1.0f, 2.0f);
852 		assertList(parse(s, "1,2", double[].class), 1.0, 2.0);
853 		assertList(parse(s, "1,2", Double[].class), 1.0, 2.0);
854 		assertList(parse(s, "1,2", List.class, Double.class), 1.0, 2.0);
855 		assertList(parse(s, "1,2", String[].class), "1.0", "2.0");
856 		assertList(parse(s, "1,2", List.class, String.class), "1.0", "2.0");
857 		assertList(parse(s, "1,2", Object[].class), 1.0, 2.0);
858 		assertList(parse(s, "1,2", List.class, Object.class), 1.0, 2.0);
859 		assertBeans(parse(s,  "1,2", G3[].class), "f", "1.0", "2.0");
860 		assertBeans(parse(s,  "1,2", List.class, G3.class), "f", "1.0", "2.0");
861 		assertJson("'G4-[1.0,2.0]'", parse(s,  "1,2", G4.class));
862 	}
863 
864 	@Test void g06_numberType_double_3d() throws Exception {
865 		var s = tArrayPipes(tArray(tDouble())).build();
866 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", float[][].class));
867 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, float[].class));
868 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", Float[][].class));
869 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, Float[].class));
870 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, List.class, Float.class));
871 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", double[][].class));
872 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, double[].class));
873 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", Double[][].class));
874 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, Double[].class));
875 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, List.class, Double.class));
876 		assertJson("[['1.0','2.0'],['3.0']]", parse(s, "1,2|3", String[][].class));
877 		assertJson("[['1.0','2.0'],['3.0']]", parse(s, "1,2|3", List.class, String[].class));
878 		assertJson("[['1.0','2.0'],['3.0']]", parse(s, "1,2|3", List.class, List.class, String.class));
879 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", Object[][].class));
880 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, Object[].class));
881 		assertJson("[[1.0,2.0],[3.0]]", parse(s, "1,2|3", List.class, List.class, Object.class));
882 		assertJson("[[1.0,2.0],[3.0]]", parse(s,  "1,2|3", G3[][].class));
883 		assertJson("[[1.0,2.0],[3.0]]", parse(s,  "1,2|3", List.class, G3[].class));
884 		assertJson("[[1.0,2.0],[3.0]]", parse(s,  "1,2|3", List.class, List.class, G3.class));
885 		assertJson("['G4-[1.0,2.0]','G4-[3.0]']", parse(s, "1,2|3", G4[].class));
886 		assertJson("['G4-[1.0,2.0]','G4-[3.0]']", parse(s, "1,2|3", List.class, G4.class));
887 	}
888 
889 
890 	//-----------------------------------------------------------------------------------------------------------------
891 	// type = object
892 	//-----------------------------------------------------------------------------------------------------------------
893 
894 	public static class H1 {
895 		public int f;
896 	}
897 
898 	@Test void h01_objectType() throws Exception {
899 		var s = HttpPartSchema.create().type("object").build();
900 		assertJson("{f:1}", parse(s, "f=1", H1.class));
901 		assertJson("{f:'1'}", parse(s, "f=1", JsonMap.class));
902 		var o = parse(s, "f=1", Object.class);
903 		assertBean(o, "f", "1");
904 		assertInstanceOf(JsonMap.class, o);
905 	}
906 
907 	@Test void h02_objectType_2d() throws Exception {
908 		var s = tArrayUon(tObject()).build();
909 		assertJson("[{f:1},{f:2}]", parse(s, "@((f=1),(f=2))", H1[].class));
910 		assertJson("[{f:1},{f:2}]", parse(s, "@((f=1),(f=2))", List.class, H1.class));
911 		assertJson("[{f:1},{f:2}]", parse(s, "@((f=1),(f=2))", JsonMap[].class));
912 		assertJson("[{f:1},{f:2}]", parse(s, "@((f=1),(f=2))", List.class, JsonMap.class));
913 		assertJson("[{f:1},{f:2}]", parse(s, "@((f=1),(f=2))", Object[].class));
914 		assertJson("[{f:1},{f:2}]", parse(s, "@((f=1),(f=2))", List.class, Object.class));
915 		var o = parse(s, "@((f=1),(f=2))", Object.class);
916 		assertBeans(o, "f", "1", "2");
917 		assertInstanceOf(JsonList.class, o);
918 	}
919 
920 	@Test void h03_objectType_3d() throws Exception {
921 		var s = tArrayUon(tArray(tObject())).build();
922 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", H1[][].class));
923 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", List.class, H1[].class));
924 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", List.class, List.class, H1.class));
925 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", JsonMap[][].class));
926 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", List.class, JsonMap[].class));
927 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", List.class, List.class, JsonMap.class));
928 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", Object[][].class));
929 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", List.class, Object[].class));
930 		assertJson("[[{f:1},{f:2}],[{f:3}]]", parse(s, "@(@((f=1),(f=2)),@((f=3)))", List.class, List.class, Object.class));
931 		var o = parse(s, "@(@((f=1),(f=2)),@((f=3)))", Object.class);
932 		assertBeans(o, "#{f}", "[{1},{2}]", "[{3}]");
933 		assertInstanceOf(JsonList.class, o);
934 	}
935 
936 	public static class H2 {
937 		public Object f01, f02, f03, f04, f05, f06, f07, f08, f09, f10, f11, f12, f99;
938 	}
939 
940 	@Test void h04_objectType_simpleProperties() throws Exception {
941 		var s = tObject()
942 			.p("f01", tString())
943 			.p("f02", tByte())
944 			.p("f04", tDateTime())
945 			.p("f05", tBinary())
946 			.p("f06", tBinarySpaced())
947 			.p("f07", tUon())
948 			.p("f08", tInteger())
949 			.p("f09", tInt64())
950 			.p("f10", tNumber())
951 			.p("f11", tDouble())
952 			.p("f12", tBoolean())
953 			.ap(tInteger())
954 			.build();
955 
956 		var foob = "foo".getBytes();
957 		var in = "f01=foo,f02="+base64Encode(foob)+",f04=2012-12-21T12:34:56Z,f05="+toHex(foob)+",f06="+toSpacedHex(foob)+",f07=foo,f08=1,f09=1,f10=1,f11=1,f12=true,f99=1";
958 
959 		var h2 = parse(s, in, H2.class);
960 		assertBean(h2, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "foo,666F6F,2012-12-21T12:34:56Z,666F6F,666F6F,foo,1,1,1.0,1.0,true,1");
961 		assertInstanceOf(String.class, h2.f01);
962 		assertInstanceOf(byte[].class, h2.f02);
963 		assertInstanceOf(GregorianCalendar.class, h2.f04);
964 		assertInstanceOf(byte[].class, h2.f05);
965 		assertInstanceOf(byte[].class, h2.f06);
966 		assertInstanceOf(String.class, h2.f07);
967 		assertInstanceOf(Integer.class, h2.f08);
968 		assertInstanceOf(Long.class, h2.f09);
969 		assertInstanceOf(Float.class, h2.f10);
970 		assertInstanceOf(Double.class, h2.f11);
971 		assertInstanceOf(Boolean.class, h2.f12);
972 		assertInstanceOf(Integer.class, h2.f99);
973 
974 		var om = parse(s, in, JsonMap.class);
975 		assertMap(om, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "foo,666F6F,2012-12-21T12:34:56Z,666F6F,666F6F,foo,1,1,1.0,1.0,true,1");
976 		assertInstanceOf(String.class, om.get("f01"));
977 		assertInstanceOf(byte[].class, om.get("f02"));
978 		assertInstanceOf(GregorianCalendar.class, om.get("f04"));
979 		assertInstanceOf(byte[].class, om.get("f05"));
980 		assertInstanceOf(byte[].class, om.get("f06"));
981 		assertInstanceOf(String.class, om.get("f07"));
982 		assertInstanceOf(Integer.class, om.get("f08"));
983 		assertInstanceOf(Long.class, om.get("f09"));
984 		assertInstanceOf(Float.class, om.get("f10"));
985 		assertInstanceOf(Double.class, om.get("f11"));
986 		assertInstanceOf(Boolean.class, om.get("f12"));
987 		assertInstanceOf(Integer.class, om.get("f99"));
988 
989 		om = (JsonMap)parse(s, in, Object.class);
990 		assertMap(om, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "foo,666F6F,2012-12-21T12:34:56Z,666F6F,666F6F,foo,1,1,1.0,1.0,true,1");
991 		assertInstanceOf(String.class, om.get("f01"));
992 		assertInstanceOf(byte[].class, om.get("f02"));
993 		assertInstanceOf(GregorianCalendar.class, om.get("f04"));
994 		assertInstanceOf(byte[].class, om.get("f05"));
995 		assertInstanceOf(byte[].class, om.get("f06"));
996 		assertInstanceOf(String.class, om.get("f07"));
997 		assertInstanceOf(Integer.class, om.get("f08"));
998 		assertInstanceOf(Long.class, om.get("f09"));
999 		assertInstanceOf(Float.class, om.get("f10"));
1000 		assertInstanceOf(Double.class, om.get("f11"));
1001 		assertInstanceOf(Boolean.class, om.get("f12"));
1002 		assertInstanceOf(Integer.class, om.get("f99"));
1003 	}
1004 
1005 	@Test void h05_objectType_arrayProperties() throws Exception {
1006 		var s = tObject()
1007 			.p("f01", tArray(tString()))
1008 			.p("f02", tArray(tByte()))
1009 			.p("f04", tArray(tDateTime()))
1010 			.p("f05", tArray(tBinary()))
1011 			.p("f06", tArray(tBinarySpaced()))
1012 			.p("f07", tArray(tUon()))
1013 			.p("f08", tArray(tInteger()))
1014 			.p("f09", tArray(tInt64()))
1015 			.p("f10", tArray(tNumber()))
1016 			.p("f11", tArray(tDouble()))
1017 			.p("f12", tArray(tBoolean()))
1018 			.ap(tArray(tInteger()))
1019 			.build();
1020 
1021 		var foob = "foo".getBytes();
1022 		var in = "f01=foo,f02="+base64Encode(foob)+",f04=2012-12-21T12:34:56Z,f05="+toHex(foob)+",f06="+toSpacedHex(foob)+",f07=foo,f08=1,f09=1,f10=1,f11=1,f12=true,f99=1";
1023 
1024 		var h2 = parse(s, in, H2.class);
1025 		assertBean(h2, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "[foo],[666F6F],[2012-12-21T12:34:56Z],[666F6F],[666F6F],[foo],[1],[1],[1.0],[1.0],[true],[1]");
1026 
1027 		var om = parse(s, in, JsonMap.class);
1028 		assertMap(om, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "[foo],[666F6F],[2012-12-21T12:34:56Z],[666F6F],[666F6F],[foo],[1],[1],[1.0],[1.0],[true],[1]");
1029 
1030 		om = (JsonMap)parse(s, in, Object.class);
1031 		assertMap(om, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "[foo],[666F6F],[2012-12-21T12:34:56Z],[666F6F],[666F6F],[foo],[1],[1],[1.0],[1.0],[true],[1]");
1032 	}
1033 
1034 	@Test void h06_objectType_arrayProperties_pipes() throws Exception {
1035 		var s = tObject()
1036 			.p("f01", tArrayPipes(tString()))
1037 			.p("f02", tArrayPipes(tByte()))
1038 			.p("f04", tArrayPipes(tDateTime()))
1039 			.p("f05", tArrayPipes(tBinary()))
1040 			.p("f06", tArrayPipes(tBinarySpaced()))
1041 			.p("f07", tArrayPipes(tUon()))
1042 			.p("f08", tArrayPipes(tInteger()))
1043 			.p("f09", tArrayPipes(tInt64()))
1044 			.p("f10", tArrayPipes(tNumber()))
1045 			.p("f11", tArrayPipes(tDouble()))
1046 			.p("f12", tArrayPipes(tBoolean()))
1047 			.ap(tArrayPipes(tInteger()))
1048 			.build();
1049 
1050 		var foob = "foo".getBytes();
1051 		var barb = "bar".getBytes();
1052 		var in = "f01=foo|bar,f02="+base64Encode(foob)+"|"+base64Encode(barb)+",f04=2012-12-21T12:34:56Z|2012-12-21T12:34:56Z,f05="+toHex(foob)+"|"+toHex(barb)+",f06="+toSpacedHex(foob)+"|"+toSpacedHex(barb)+",f07=foo|bar,f08=1|2,f09=1|2,f10=1|2,f11=1|2,f12=true|true,f99=1|2";
1053 
1054 		var h2 = parse(s, in, H2.class);
1055 		assertBean(h2, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "[foo,bar],[666F6F,626172],[2012-12-21T12:34:56Z,2012-12-21T12:34:56Z],[666F6F,626172],[666F6F,626172],[foo,bar],[1,2],[1,2],[1.0,2.0],[1.0,2.0],[true,true],[1,2]");
1056 
1057 		var om = parse(s, in, JsonMap.class);
1058 		assertMap(om, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "[foo,bar],[666F6F,626172],[2012-12-21T12:34:56Z,2012-12-21T12:34:56Z],[666F6F,626172],[666F6F,626172],[foo,bar],[1,2],[1,2],[1.0,2.0],[1.0,2.0],[true,true],[1,2]");
1059 
1060 		om = (JsonMap)parse(s, in, Object.class);
1061 		assertMap(om, "f01,f02,f04,f05,f06,f07,f08,f09,f10,f11,f12,f99", "[foo,bar],[666F6F,626172],[2012-12-21T12:34:56Z,2012-12-21T12:34:56Z],[666F6F,626172],[666F6F,626172],[foo,bar],[1,2],[1,2],[1.0,2.0],[1.0,2.0],[true,true],[1,2]");
1062 	}
1063 }