@@ -501,13 +501,63 @@ public void testArrayAccessorsReturnNullForNullValue() throws Exception {
501501 try (JSONEachRowFormatReader reader = new JSONEachRowFormatReader (
502502 new StubJsonParser (Collections .singletonList (r )))) {
503503 reader .next ();
504+
505+ // By name: every array accessor must propagate the null cleanly
506+ // rather than throw NullPointerException or fabricate an empty array.
504507 Assert .assertNull (reader .getList ("v" ));
508+ Assert .assertNull (reader .getByteArray ("v" ));
509+ Assert .assertNull (reader .getShortArray ("v" ));
505510 Assert .assertNull (reader .getIntArray ("v" ));
506511 Assert .assertNull (reader .getLongArray ("v" ));
512+ Assert .assertNull (reader .getFloatArray ("v" ));
507513 Assert .assertNull (reader .getDoubleArray ("v" ));
508514 Assert .assertNull (reader .getBooleanArray ("v" ));
509515 Assert .assertNull (reader .getStringArray ("v" ));
510516 Assert .assertNull (reader .getObjectArray ("v" ));
517+
518+ // By 1-based index: the same null-propagation guarantee must hold
519+ // for the index-based overloads, which delegate to the name-based
520+ // implementations through the inferred schema.
521+ Assert .assertNull (reader .getList (1 ));
522+ Assert .assertNull (reader .getByteArray (1 ));
523+ Assert .assertNull (reader .getShortArray (1 ));
524+ Assert .assertNull (reader .getIntArray (1 ));
525+ Assert .assertNull (reader .getLongArray (1 ));
526+ Assert .assertNull (reader .getFloatArray (1 ));
527+ Assert .assertNull (reader .getDoubleArray (1 ));
528+ Assert .assertNull (reader .getBooleanArray (1 ));
529+ Assert .assertNull (reader .getStringArray (1 ));
530+ Assert .assertNull (reader .getObjectArray (1 ));
531+ }
532+ }
533+
534+ @ Test
535+ public void testArrayAccessorsRejectNullElement () throws Exception {
536+ // A null element in a JSON array cannot be stored into a Java
537+ // primitive array slot, so getPrimitiveArray must surface this rather
538+ // than substitute a zero/false value silently. The String and Object
539+ // overloads are allowed to keep the null element.
540+ try (JSONEachRowFormatReader reader = readerOf (row (
541+ "ints" , Arrays .asList (1 , null , 3 ),
542+ "bools" , Arrays .asList (Boolean .TRUE , null ),
543+ "strs" , Arrays .asList ("a" , null , "c" ),
544+ "objs" , Arrays .asList ("x" , null )))) {
545+ reader .next ();
546+
547+ assertThrowsRuntime (() -> reader .getIntArray ("ints" ));
548+ assertThrowsRuntime (() -> reader .getIntArray (1 ));
549+ assertThrowsRuntime (() -> reader .getLongArray ("ints" ));
550+ assertThrowsRuntime (() -> reader .getShortArray ("ints" ));
551+ assertThrowsRuntime (() -> reader .getByteArray ("ints" ));
552+ assertThrowsRuntime (() -> reader .getFloatArray ("ints" ));
553+ assertThrowsRuntime (() -> reader .getDoubleArray ("ints" ));
554+ assertThrowsRuntime (() -> reader .getBooleanArray ("bools" ));
555+
556+ // The non-primitive container accessors keep nulls.
557+ Assert .assertEquals (reader .getStringArray ("strs" ), new String [] {"a" , null , "c" });
558+ Object [] objs = reader .getObjectArray ("objs" );
559+ Assert .assertEquals (objs .length , 2 );
560+ Assert .assertNull (objs [1 ]);
511561 }
512562 }
513563
@@ -538,6 +588,76 @@ public void testArrayAccessorsRejectNonArrayValues() throws Exception {
538588 }
539589 }
540590
591+ @ Test
592+ public void testArrayAccessorsByIndex () throws Exception {
593+ // Mirrors testArrayAccessorsCoercePrimitiveElements but addresses every
594+ // typed array accessor through its 1-based column index. This ensures
595+ // the index-based overloads delegate correctly through the inferred
596+ // schema, even for arrays where the schema only records "Array" without
597+ // a specific element type.
598+ try (JSONEachRowFormatReader reader = readerOf (row (
599+ "ints" , Arrays .asList (1 , 2 , 3 ),
600+ "longs" , Arrays .asList (10L , 20L , 30L ),
601+ "shorts" , Arrays .asList ((short ) 4 , (short ) 5 ),
602+ "bytes" , Arrays .asList ((byte ) 6 , (byte ) 7 ),
603+ "doubles" , Arrays .asList (1.5d , 2.5d ),
604+ "floats" , Arrays .asList (1.0f , 2.0f ),
605+ "bools" , Arrays .asList (Boolean .TRUE , Boolean .FALSE ),
606+ "strs" , Arrays .asList ("a" , "b" )))) {
607+ reader .next ();
608+
609+ Assert .assertEquals (reader .getIntArray (1 ), new int [] {1 , 2 , 3 });
610+ Assert .assertEquals (reader .getLongArray (2 ), new long [] {10L , 20L , 30L });
611+ Assert .assertEquals (reader .getShortArray (3 ), new short [] {(short ) 4 , (short ) 5 });
612+ Assert .assertEquals (reader .getByteArray (4 ), new byte [] {(byte ) 6 , (byte ) 7 });
613+ Assert .assertEquals (reader .getDoubleArray (5 ), new double [] {1.5d , 2.5d }, 1e-9 );
614+ Assert .assertEquals (reader .getFloatArray (6 ), new float [] {1.0f , 2.0f }, 1e-6f );
615+ Assert .assertEquals (reader .getBooleanArray (7 ), new boolean [] {true , false });
616+ Assert .assertEquals (reader .getStringArray (8 ), new String [] {"a" , "b" });
617+
618+ // getList and getObjectArray by index, on the first column.
619+ List <Integer > list = reader .getList (1 );
620+ Assert .assertEquals (list , Arrays .asList (1 , 2 , 3 ));
621+ Object [] objs = reader .getObjectArray (1 );
622+ Assert .assertEquals (objs .length , 3 );
623+ }
624+ }
625+
626+ @ Test
627+ public void testGetBooleanArrayFromNumericList () throws Exception {
628+ // Exercises the Number branch in coerceToComponent for boolean[]: the
629+ // reader treats 0 as false and any non-zero value as true, regardless
630+ // of whether the parser materialized the element as Integer, Long, or
631+ // BigDecimal.
632+ try (JSONEachRowFormatReader reader = readerOf (row (
633+ "as_int" , Arrays .asList (0 , 1 , 2 , -1 ),
634+ "as_long" , Arrays .asList (0L , 5L ),
635+ "as_big_decimal" , Arrays .asList (BigDecimal .ZERO , new BigDecimal ("3" ))))) {
636+ reader .next ();
637+
638+ Assert .assertEquals (reader .getBooleanArray ("as_int" ),
639+ new boolean [] {false , true , true , true });
640+ Assert .assertEquals (reader .getBooleanArray ("as_long" ),
641+ new boolean [] {false , true });
642+ Assert .assertEquals (reader .getBooleanArray ("as_big_decimal" ),
643+ new boolean [] {false , true });
644+ }
645+ }
646+
647+ @ Test
648+ public void testGetBooleanArrayRejectsNonBooleanNonNumberElements () throws Exception {
649+ // String elements cannot be coerced into boolean[] (we don't accept
650+ // string-to-boolean parsing on the scalar getBoolean accessor either),
651+ // so getBooleanArray must surface a RuntimeException sourced from the
652+ // illegal-coerce branch in coerceToComponent.
653+ try (JSONEachRowFormatReader reader = readerOf (row (
654+ "v" , Arrays .asList ("true" , "false" )))) {
655+ reader .next ();
656+ assertThrowsRuntime (() -> reader .getBooleanArray ("v" ));
657+ assertThrowsRuntime (() -> reader .getBooleanArray (1 ));
658+ }
659+ }
660+
541661 @ Test
542662 public void testArrayAccessorsCoercePrimitiveElements () throws Exception {
543663 // Different parsers materialize numbers as different boxed types
0 commit comments