diff --git a/arrow-json/src/reader/list_array.rs b/arrow-json/src/reader/list_array.rs index 63644964c30c..fc6af5907971 100644 --- a/arrow-json/src/reader/list_array.rs +++ b/arrow-json/src/reader/list_array.rs @@ -112,16 +112,13 @@ impl ArrayDecoder for ListLikeArrayDeco sizes.push(offsets[i] - offsets[i - 1]); } offsets.pop(); - // SAFETY: offsets and sizes are constructed correctly from the tape - let array = unsafe { - GenericListViewArray::::new_unchecked( - self.field.clone(), - ScalarBuffer::from(offsets), - ScalarBuffer::from(sizes), - values, - nulls, - ) - }; + let array = GenericListViewArray::::try_new( + self.field.clone(), + ScalarBuffer::from(offsets), + ScalarBuffer::from(sizes), + values, + nulls, + )?; Ok(Arc::new(array)) } else { // SAFETY: offsets are built monotonically starting from 0 diff --git a/arrow-json/src/reader/mod.rs b/arrow-json/src/reader/mod.rs index ea4cbe2664f6..44a686facc59 100644 --- a/arrow-json/src/reader/mod.rs +++ b/arrow-json/src/reader/mod.rs @@ -2316,6 +2316,34 @@ mod tests { assert_read_list_view::(); } + #[test] + fn test_read_list_view_rejects_null_non_nullable_child() { + let field = Arc::new(Field::new("item", DataType::Int32, false)); + for (data_type, array_type) in [ + (DataType::ListView(field.clone()), "ListViewArray"), + (DataType::LargeListView(field.clone()), "LargeListViewArray"), + ] { + let schema = Arc::new(Schema::new(vec![Field::new("lv", data_type, true)])); + let buf = r#" + {"lv": [1, 2, 3]} + {"lv": [4, null]} + "#; + + let error = ReaderBuilder::new(schema) + .build(Cursor::new(buf.as_bytes())) + .unwrap() + .collect::, _>>() + .unwrap_err(); + + assert_eq!( + error.to_string(), + format!( + "Invalid argument error: Non-nullable field of {array_type} \"item\" cannot contain nulls" + ) + ); + } + } + #[test] fn test_fixed_size_list() { let buf = r#"