1use std::convert::TryFrom;
7use std::sync::Arc;
8
9use arrow_array::builder::{GenericStringBuilder, LargeBinaryBuilder};
10use arrow_array::cast::AsArray;
11use arrow_array::{
12 Array, ArrayRef, FixedSizeListArray, GenericStringArray, LargeBinaryArray, LargeListArray,
13 LargeStringArray, ListArray, MapArray, OffsetSizeTrait, RecordBatch, StringArray, StructArray,
14};
15use arrow_schema::{ArrowError, DataType, Field as ArrowField, Fields, Schema};
16use jsonb::OwnedJsonb;
17use jsonb::jsonpath::{JsonPath, Selector};
18
19use crate::ARROW_EXT_NAME_KEY;
20
21pub const JSON_EXT_NAME: &str = "lance.json";
23
24pub const ARROW_JSON_EXT_NAME: &str = "arrow.json";
26
27pub fn is_json_field(field: &ArrowField) -> bool {
29 field.data_type() == &DataType::LargeBinary
30 && field
31 .metadata()
32 .get(ARROW_EXT_NAME_KEY)
33 .map(|name| name == JSON_EXT_NAME)
34 .unwrap_or_default()
35}
36
37pub fn is_arrow_json_field(field: &ArrowField) -> bool {
39 (field.data_type() == &DataType::Utf8 || field.data_type() == &DataType::LargeUtf8)
41 && field
42 .metadata()
43 .get(ARROW_EXT_NAME_KEY)
44 .map(|name| name == ARROW_JSON_EXT_NAME)
45 .unwrap_or_default()
46}
47
48pub fn has_json_fields(field: &ArrowField) -> bool {
50 if is_json_field(field) {
51 return true;
52 }
53
54 match field.data_type() {
55 DataType::Struct(fields) => fields.iter().any(|f| has_json_fields(f)),
56 DataType::List(f) | DataType::LargeList(f) | DataType::FixedSizeList(f, _) => {
57 has_json_fields(f)
58 }
59 DataType::Map(f, _) => has_json_fields(f),
60 _ => false,
61 }
62}
63
64pub fn has_arrow_json_fields(field: &ArrowField) -> bool {
66 if is_arrow_json_field(field) {
67 return true;
68 }
69
70 match field.data_type() {
71 DataType::Struct(fields) => fields.iter().any(|f| has_arrow_json_fields(f)),
72 DataType::List(f) | DataType::LargeList(f) | DataType::FixedSizeList(f, _) => {
73 has_arrow_json_fields(f)
74 }
75 DataType::Map(f, _) => has_arrow_json_fields(f),
76 _ => false,
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum JsonEncoding {
83 Jsonb,
86 Text,
89}
90
91impl JsonEncoding {
92 pub fn of_field(field: &ArrowField) -> Option<Self> {
95 if is_json_field(field) {
96 Some(Self::Jsonb)
97 } else if is_arrow_json_field(field) {
98 Some(Self::Text)
99 } else {
100 None
101 }
102 }
103}
104
105#[derive(Debug, Clone, Copy)]
112pub struct JsonValues<'a> {
113 encoding: JsonEncoding,
114 array: &'a ArrayRef,
115}
116
117impl<'a> JsonValues<'a> {
118 pub fn try_new(field: &ArrowField, array: &'a ArrayRef) -> Option<Self> {
121 JsonEncoding::of_field(field).map(|encoding| Self { encoding, array })
122 }
123
124 pub fn encoding(&self) -> JsonEncoding {
125 self.encoding
126 }
127
128 pub fn to_jsonb(&self) -> Result<LargeBinaryArray, ArrowError> {
130 match self.encoding {
131 JsonEncoding::Jsonb => Ok(self.array.as_binary::<i64>().clone()),
132 JsonEncoding::Text => Ok(JsonArray::try_from(self.array.clone())?.into_inner()),
133 }
134 }
135
136 pub fn to_text(&self) -> ArrayRef {
139 match self.encoding {
140 JsonEncoding::Jsonb => Arc::new(decode_jsonb_array::<i64>(self.array.as_binary())),
141 JsonEncoding::Text => self.array.clone(),
142 }
143 }
144}
145
146pub fn json_field(name: &str, nullable: bool) -> ArrowField {
148 let mut field = ArrowField::new(name, DataType::LargeBinary, nullable);
149 let mut metadata = std::collections::HashMap::new();
150 metadata.insert(ARROW_EXT_NAME_KEY.to_string(), JSON_EXT_NAME.to_string());
151 field.set_metadata(metadata);
152 field
153}
154
155#[derive(Debug, Clone)]
157pub struct JsonArray {
158 inner: LargeBinaryArray,
159}
160
161impl JsonArray {
162 pub fn try_from_iter<I, S>(iter: I) -> Result<Self, ArrowError>
164 where
165 I: IntoIterator<Item = Option<S>>,
166 S: AsRef<str>,
167 {
168 let mut builder = LargeBinaryBuilder::new();
169
170 for json_str in iter {
171 match json_str {
172 Some(s) => {
173 let encoded = encode_json(s.as_ref()).map_err(|e| {
174 ArrowError::InvalidArgumentError(format!("Failed to encode JSON: {}", e))
175 })?;
176 builder.append_value(&encoded);
177 }
178 None => builder.append_null(),
179 }
180 }
181
182 Ok(Self {
183 inner: builder.finish(),
184 })
185 }
186
187 pub fn into_inner(self) -> LargeBinaryArray {
189 self.inner
190 }
191
192 pub fn inner(&self) -> &LargeBinaryArray {
194 &self.inner
195 }
196
197 pub fn value(&self, i: usize) -> Result<String, ArrowError> {
199 if self.inner.is_null(i) {
200 return Err(ArrowError::InvalidArgumentError(
201 "Value is null".to_string(),
202 ));
203 }
204
205 let jsonb_bytes = self.inner.value(i);
206 Ok(decode_json(jsonb_bytes))
207 }
208
209 pub fn value_bytes(&self, i: usize) -> &[u8] {
211 self.inner.value(i)
212 }
213
214 pub fn json_path(&self, i: usize, path: &str) -> Result<Option<String>, ArrowError> {
216 if self.inner.is_null(i) {
217 return Ok(None);
218 }
219
220 let path = parse_json_path(path)?;
221 Ok(select_json_path(self.inner.value(i), &path)?.map(|value| value.to_string()))
222 }
223
224 pub fn to_arrow_json(&self) -> ArrayRef {
226 Arc::new(decode_jsonb_array::<i32>(&self.inner))
227 }
228
229 pub fn len(&self) -> usize {
230 self.inner.len()
231 }
232
233 pub fn is_empty(&self) -> bool {
234 self.inner.is_empty()
235 }
236
237 pub fn is_null(&self, i: usize) -> bool {
238 self.inner.is_null(i)
239 }
240}
241
242impl TryFrom<StringArray> for JsonArray {
244 type Error = ArrowError;
245
246 fn try_from(array: StringArray) -> Result<Self, Self::Error> {
247 Self::try_from(&array)
248 }
249}
250
251impl TryFrom<&StringArray> for JsonArray {
252 type Error = ArrowError;
253
254 fn try_from(array: &StringArray) -> Result<Self, Self::Error> {
255 encode_json_text_array(array)
256 }
257}
258
259impl TryFrom<LargeStringArray> for JsonArray {
260 type Error = ArrowError;
261
262 fn try_from(array: LargeStringArray) -> Result<Self, Self::Error> {
263 Self::try_from(&array)
264 }
265}
266
267impl TryFrom<&LargeStringArray> for JsonArray {
268 type Error = ArrowError;
269
270 fn try_from(array: &LargeStringArray) -> Result<Self, Self::Error> {
271 encode_json_text_array(array)
272 }
273}
274
275fn encode_json_text_array<O: OffsetSizeTrait>(
276 array: &GenericStringArray<O>,
277) -> Result<JsonArray, ArrowError> {
278 let mut builder = LargeBinaryBuilder::with_capacity(array.len(), array.value_data().len());
279 for value in array {
280 match value {
281 Some(json_str) => {
282 let encoded = encode_json(json_str).map_err(|e| {
283 ArrowError::InvalidArgumentError(format!("Failed to encode JSON: {}", e))
284 })?;
285 builder.append_value(&encoded);
286 }
287 None => builder.append_null(),
288 }
289 }
290 Ok(JsonArray {
291 inner: builder.finish(),
292 })
293}
294
295fn decode_jsonb_array<O: OffsetSizeTrait>(array: &LargeBinaryArray) -> GenericStringArray<O> {
296 let mut builder =
297 GenericStringBuilder::<O>::with_capacity(array.len(), array.value_data().len());
298 for value in array {
299 match value {
300 Some(jsonb_bytes) => builder.append_value(decode_json(jsonb_bytes)),
301 None => builder.append_null(),
302 }
303 }
304 builder.finish()
305}
306
307impl TryFrom<ArrayRef> for JsonArray {
308 type Error = ArrowError;
309
310 fn try_from(array_ref: ArrayRef) -> Result<Self, Self::Error> {
311 match array_ref.data_type() {
312 DataType::Utf8 => {
313 let string_array = array_ref
315 .as_any()
316 .downcast_ref::<StringArray>()
317 .expect("DataType::Utf8 array must be StringArray");
318 Self::try_from(string_array)
319 }
320 DataType::LargeUtf8 => {
321 let large_string_array = array_ref
323 .as_any()
324 .downcast_ref::<LargeStringArray>()
325 .expect("DataType::LargeUtf8 array must be LargeStringArray");
326 Self::try_from(large_string_array)
327 }
328 dt => Err(ArrowError::InvalidArgumentError(format!(
329 "Unsupported array type for JSON: {:?}. Expected Utf8 or LargeUtf8",
330 dt
331 ))),
332 }
333 }
334}
335
336pub fn encode_json(json_str: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
338 let value = jsonb::parse_value(json_str.as_bytes())?;
339 Ok(value.to_vec())
340}
341
342pub fn decode_json(jsonb_bytes: &[u8]) -> String {
344 let raw_jsonb = jsonb::RawJsonb::new(jsonb_bytes);
345 raw_jsonb.to_string()
346}
347
348pub fn parse_json_path(path: &str) -> Result<JsonPath<'_>, ArrowError> {
350 jsonb::jsonpath::parse_json_path(path.as_bytes())
351 .map_err(|e| ArrowError::InvalidArgumentError(format!("Invalid JSONPath '{path}': {e}")))
352}
353
354pub fn select_json_path(
359 jsonb_bytes: &[u8],
360 path: &JsonPath<'_>,
361) -> Result<Option<OwnedJsonb>, ArrowError> {
362 Selector::new(jsonb::RawJsonb::new(jsonb_bytes))
363 .select_value(path)
364 .map_err(|e| {
365 ArrowError::InvalidArgumentError(format!("Failed to select JSONPath {path}: {e}"))
366 })
367}
368
369pub fn json_path_exists(jsonb_bytes: &[u8], path: &JsonPath<'_>) -> Result<bool, ArrowError> {
371 Selector::new(jsonb::RawJsonb::new(jsonb_bytes))
372 .exists(path)
373 .map_err(|e| {
374 ArrowError::InvalidArgumentError(format!("Failed to match JSONPath {path}: {e}"))
375 })
376}
377
378pub fn select_json_path_values(
380 jsonb_bytes: &[u8],
381 path: &JsonPath<'_>,
382) -> Result<Vec<OwnedJsonb>, ArrowError> {
383 Selector::new(jsonb::RawJsonb::new(jsonb_bytes))
384 .select_values(path)
385 .map_err(|e| {
386 ArrowError::InvalidArgumentError(format!("Failed to select JSONPath {path}: {e}"))
387 })
388}
389
390pub fn arrow_json_to_lance_json(field: &ArrowField) -> ArrowField {
392 if is_arrow_json_field(field) {
393 return field_with_extension(field, DataType::LargeBinary, JSON_EXT_NAME);
394 }
395
396 let data_type = match field.data_type() {
397 DataType::Struct(fields) => {
398 let fields = fields
399 .iter()
400 .map(|field| Arc::new(arrow_json_to_lance_json(field)))
401 .collect::<Vec<_>>();
402 DataType::Struct(Fields::from(fields))
403 }
404 DataType::List(item) => DataType::List(Arc::new(arrow_json_to_lance_json(item))),
405 DataType::LargeList(item) => DataType::LargeList(Arc::new(arrow_json_to_lance_json(item))),
406 DataType::FixedSizeList(item, size) => {
407 DataType::FixedSizeList(Arc::new(arrow_json_to_lance_json(item)), *size)
408 }
409 DataType::Map(entries, keys_sorted) => {
410 DataType::Map(Arc::new(arrow_json_to_lance_json(entries)), *keys_sorted)
411 }
412 _ => return field.clone(),
413 };
414
415 field_with_data_type(field, data_type)
416}
417
418pub fn lance_json_to_arrow_json(field: &ArrowField) -> ArrowField {
420 if is_json_field(field) {
421 return field_with_extension(field, DataType::Utf8, ARROW_JSON_EXT_NAME);
422 }
423
424 let data_type = match field.data_type() {
425 DataType::Struct(fields) => {
426 let fields = fields
427 .iter()
428 .map(|field| Arc::new(lance_json_to_arrow_json(field)))
429 .collect::<Vec<_>>();
430 DataType::Struct(Fields::from(fields))
431 }
432 DataType::List(item) => DataType::List(Arc::new(lance_json_to_arrow_json(item))),
433 DataType::LargeList(item) => DataType::LargeList(Arc::new(lance_json_to_arrow_json(item))),
434 DataType::FixedSizeList(item, size) => {
435 DataType::FixedSizeList(Arc::new(lance_json_to_arrow_json(item)), *size)
436 }
437 DataType::Map(entries, keys_sorted) => {
438 DataType::Map(Arc::new(lance_json_to_arrow_json(entries)), *keys_sorted)
439 }
440 _ => return field.clone(),
441 };
442
443 field_with_data_type(field, data_type)
444}
445
446fn field_with_data_type(field: &ArrowField, data_type: DataType) -> ArrowField {
447 ArrowField::new(field.name(), data_type, field.is_nullable())
448 .with_metadata(field.metadata().clone())
449}
450
451fn field_with_extension(
452 field: &ArrowField,
453 data_type: DataType,
454 extension_name: &str,
455) -> ArrowField {
456 let mut metadata = field.metadata().clone();
457 metadata.insert(ARROW_EXT_NAME_KEY.to_string(), extension_name.to_string());
458 ArrowField::new(field.name(), data_type, field.is_nullable()).with_metadata(metadata)
459}
460
461fn convert_json_array<F>(
462 field: &ArrowField,
463 array: &ArrayRef,
464 convert_leaf: &F,
465) -> Result<(ArrowField, ArrayRef, bool), ArrowError>
466where
467 F: Fn(&ArrowField, &ArrayRef) -> Result<Option<(ArrowField, ArrayRef)>, ArrowError>,
468{
469 if let Some((field, array)) = convert_leaf(field, array)? {
470 return Ok((field, array, true));
471 }
472
473 match field.data_type() {
474 DataType::Struct(fields) => {
475 let struct_array = array.as_struct();
476 let mut new_fields = Vec::with_capacity(fields.len());
477 let mut new_columns = Vec::with_capacity(fields.len());
478 let mut changed = false;
479
480 for (field, column) in fields.iter().zip(struct_array.columns()) {
481 let (new_field, new_column, field_changed) =
482 convert_json_array(field, column, convert_leaf)?;
483 changed |= field_changed;
484 new_fields.push(Arc::new(new_field));
485 new_columns.push(new_column);
486 }
487
488 if changed {
489 let fields = Fields::from(new_fields);
490 let new_field = field_with_data_type(field, DataType::Struct(fields.clone()));
491 let new_array =
492 StructArray::new(fields, new_columns, struct_array.nulls().cloned());
493 Ok((new_field, Arc::new(new_array) as ArrayRef, true))
494 } else {
495 Ok((field.clone(), array.clone(), false))
496 }
497 }
498 DataType::List(item) => {
499 let list_array: &ListArray = array.as_list();
500 let (new_item, new_values, changed) =
501 convert_json_array(item, list_array.values(), convert_leaf)?;
502 if changed {
503 let new_field =
504 field_with_data_type(field, DataType::List(Arc::new(new_item.clone())));
505 let new_array = ListArray::new(
506 Arc::new(new_item),
507 list_array.offsets().clone(),
508 new_values,
509 list_array.nulls().cloned(),
510 );
511 Ok((new_field, Arc::new(new_array) as ArrayRef, true))
512 } else {
513 Ok((field.clone(), array.clone(), false))
514 }
515 }
516 DataType::LargeList(item) => {
517 let list_array: &LargeListArray = array.as_list();
518 let (new_item, new_values, changed) =
519 convert_json_array(item, list_array.values(), convert_leaf)?;
520 if changed {
521 let new_field =
522 field_with_data_type(field, DataType::LargeList(Arc::new(new_item.clone())));
523 let new_array = LargeListArray::new(
524 Arc::new(new_item),
525 list_array.offsets().clone(),
526 new_values,
527 list_array.nulls().cloned(),
528 );
529 Ok((new_field, Arc::new(new_array) as ArrayRef, true))
530 } else {
531 Ok((field.clone(), array.clone(), false))
532 }
533 }
534 DataType::FixedSizeList(item, size) => {
535 let list_array: &FixedSizeListArray = array.as_fixed_size_list();
536 let (new_item, new_values, changed) =
537 convert_json_array(item, list_array.values(), convert_leaf)?;
538 if changed {
539 let new_field = field_with_data_type(
540 field,
541 DataType::FixedSizeList(Arc::new(new_item.clone()), *size),
542 );
543 let new_array = FixedSizeListArray::try_new_with_length(
544 Arc::new(new_item),
545 *size,
546 new_values,
547 list_array.nulls().cloned(),
548 list_array.len(),
549 )?;
550 Ok((new_field, Arc::new(new_array) as ArrayRef, true))
551 } else {
552 Ok((field.clone(), array.clone(), false))
553 }
554 }
555 DataType::Map(entries, keys_sorted) => {
556 let map_array = array
557 .as_any()
558 .downcast_ref::<MapArray>()
559 .expect("DataType::Map array must be MapArray");
560 let entries_array = Arc::new(map_array.entries().clone()) as ArrayRef;
561 let (new_entries, new_entries_array, changed) =
562 convert_json_array(entries, &entries_array, convert_leaf)?;
563 if changed {
564 let entries_struct = new_entries_array
565 .as_any()
566 .downcast_ref::<StructArray>()
567 .expect("Map entries must be StructArray")
568 .clone();
569 let new_field = field_with_data_type(
570 field,
571 DataType::Map(Arc::new(new_entries.clone()), *keys_sorted),
572 );
573 let new_array = MapArray::new(
574 Arc::new(new_entries),
575 map_array.offsets().clone(),
576 entries_struct,
577 map_array.nulls().cloned(),
578 *keys_sorted,
579 );
580 Ok((new_field, Arc::new(new_array) as ArrayRef, true))
581 } else {
582 Ok((field.clone(), array.clone(), false))
583 }
584 }
585 _ => Ok((field.clone(), array.clone(), false)),
586 }
587}
588
589fn convert_arrow_json_array(
590 field: &ArrowField,
591 array: &ArrayRef,
592) -> Result<(ArrowField, ArrayRef, bool), ArrowError> {
593 convert_json_array(field, array, &|field, array| {
594 if is_arrow_json_field(field) {
595 let json_array = JsonArray::try_from(array.clone())?;
596 Ok(Some((
597 arrow_json_to_lance_json(field),
598 Arc::new(json_array.into_inner()) as ArrayRef,
599 )))
600 } else {
601 Ok(None)
602 }
603 })
604}
605
606fn convert_lance_json_array(
607 field: &ArrowField,
608 array: &ArrayRef,
609) -> Result<(ArrowField, ArrayRef, bool), ArrowError> {
610 convert_json_array(field, array, &|field, array| {
611 if is_json_field(field) {
612 Ok(Some((
613 lance_json_to_arrow_json(field),
614 Arc::new(decode_jsonb_array::<i32>(array.as_binary())) as ArrayRef,
615 )))
616 } else {
617 Ok(None)
618 }
619 })
620}
621
622pub fn convert_lance_json_to_arrow(
624 batch: &arrow_array::RecordBatch,
625) -> Result<arrow_array::RecordBatch, ArrowError> {
626 let schema = batch.schema();
627 let mut needs_conversion = false;
628 let mut new_fields = Vec::with_capacity(schema.fields().len());
629 let mut new_columns = Vec::with_capacity(batch.num_columns());
630
631 for (i, field) in schema.fields().iter().enumerate() {
632 let column = batch.column(i);
633 let (new_field, new_column, changed) = convert_lance_json_array(field, column)?;
634
635 needs_conversion |= changed;
636 new_fields.push(new_field);
637 new_columns.push(new_column);
638 }
639
640 if needs_conversion {
641 let new_schema = Arc::new(Schema::new_with_metadata(
642 new_fields,
643 schema.metadata().clone(),
644 ));
645 RecordBatch::try_new(new_schema, new_columns)
646 } else {
647 Ok(batch.clone())
649 }
650}
651
652pub fn convert_json_columns(
654 batch: &arrow_array::RecordBatch,
655) -> Result<arrow_array::RecordBatch, ArrowError> {
656 let schema = batch.schema();
657 let mut needs_conversion = false;
658 let mut new_fields = Vec::with_capacity(schema.fields().len());
659 let mut new_columns = Vec::with_capacity(batch.num_columns());
660
661 for (i, field) in schema.fields().iter().enumerate() {
662 let column = batch.column(i);
663 let (new_field, new_column, changed) = convert_arrow_json_array(field, column)?;
664
665 needs_conversion |= changed;
666 new_fields.push(new_field);
667 new_columns.push(new_column);
668 }
669
670 if needs_conversion {
671 let new_schema = Arc::new(Schema::new_with_metadata(
672 new_fields,
673 schema.metadata().clone(),
674 ));
675 RecordBatch::try_new(new_schema, new_columns)
676 } else {
677 Ok(batch.clone())
679 }
680}
681
682#[cfg(test)]
683mod tests {
684 use super::*;
685
686 #[test]
687 fn test_json_field_creation() {
688 let field = json_field("data", true);
689 assert_eq!(field.name(), "data");
690 assert_eq!(field.data_type(), &DataType::LargeBinary);
691 assert!(field.is_nullable());
692 assert!(is_json_field(&field));
693 }
694
695 #[test]
696 fn test_json_array_from_strings() {
697 let json_strings = vec![
698 Some(r#"{"name": "Alice", "age": 30}"#),
699 None,
700 Some(r#"{"name": "Bob", "age": 25}"#),
701 ];
702
703 let array = JsonArray::try_from_iter(json_strings).unwrap();
704 assert_eq!(array.len(), 3);
705 assert!(!array.is_null(0));
706 assert!(array.is_null(1));
707 assert!(!array.is_null(2));
708
709 let decoded = array.value(0).unwrap();
710 assert!(decoded.contains("Alice"));
711 }
712
713 #[test]
714 fn test_json_array_from_string_array() {
715 let string_array = StringArray::from(vec![
716 Some(r#"{"name": "Alice"}"#),
717 Some(r#"{"name": "Bob"}"#),
718 None,
719 ]);
720
721 let json_array = JsonArray::try_from(string_array).unwrap();
722 assert_eq!(json_array.len(), 3);
723 assert!(!json_array.is_null(0));
724 assert!(!json_array.is_null(1));
725 assert!(json_array.is_null(2));
726 }
727
728 #[test]
729 fn test_json_path_extraction() {
730 let json_array = JsonArray::try_from_iter(vec![
731 Some(r#"{"user": {"name": "Alice", "age": 30}}"#),
732 Some(r#"{"user": {"name": "Bob"}}"#),
733 ])
734 .unwrap();
735
736 let name = json_array.json_path(0, "$.user.name").unwrap();
737 assert_eq!(name, Some("\"Alice\"".to_string()));
738
739 let age = json_array.json_path(1, "$.user.age").unwrap();
740 assert_eq!(age, None);
741
742 let json_array =
744 JsonArray::try_from_iter(vec![Some(r#"{"a": [{"b": 1}, {"b": 2}]}"#)]).unwrap();
745 let bs = json_array.json_path(0, "$.a[*].b").unwrap();
746 assert_eq!(bs, Some("[1,2]".to_string()));
747 }
748
749 #[test]
750 fn test_json_values_read_either_encoding() {
751 let docs = vec![Some(r#"{"a":1}"#), None];
752 let text: ArrayRef = Arc::new(StringArray::from(docs.clone()));
753 let jsonb: ArrayRef = Arc::new(JsonArray::try_from_iter(docs).unwrap().into_inner());
754 let mut text_field = ArrowField::new("j", DataType::Utf8, true);
755 text_field.set_metadata(std::collections::HashMap::from([(
756 ARROW_EXT_NAME_KEY.to_string(),
757 ARROW_JSON_EXT_NAME.to_string(),
758 )]));
759 let jsonb_field = json_field("j", true);
760
761 let from_text = JsonValues::try_new(&text_field, &text).unwrap();
762 let from_jsonb = JsonValues::try_new(&jsonb_field, &jsonb).unwrap();
763 assert_eq!(from_text.encoding(), JsonEncoding::Text);
764 assert_eq!(from_jsonb.encoding(), JsonEncoding::Jsonb);
765
766 assert_eq!(&from_text.to_jsonb().unwrap(), jsonb.as_binary::<i64>());
767 assert_eq!(&from_jsonb.to_jsonb().unwrap(), jsonb.as_binary::<i64>());
768 assert_eq!(&from_text.to_text(), &text);
769 let decoded = from_jsonb.to_text();
770 let decoded = decoded.as_string::<i64>();
771 assert_eq!(decoded.value(0), r#"{"a":1}"#);
772 assert!(decoded.is_null(1));
773
774 let plain = ArrowField::new("j", DataType::Utf8, true);
775 assert!(JsonValues::try_new(&plain, &text).is_none());
776 }
777
778 #[test]
779 fn test_convert_json_columns() {
780 let json_strings = vec![Some(r#"{"name": "Alice"}"#), Some(r#"{"name": "Bob"}"#)];
782 let json_arr = StringArray::from(json_strings);
783
784 let mut field = ArrowField::new("data", DataType::Utf8, false);
786 let mut metadata = std::collections::HashMap::new();
787 metadata.insert(
788 ARROW_EXT_NAME_KEY.to_string(),
789 ARROW_JSON_EXT_NAME.to_string(),
790 );
791 field.set_metadata(metadata);
792
793 let schema = Arc::new(Schema::new(vec![field]));
794 let batch = RecordBatch::try_new(schema, vec![Arc::new(json_arr) as ArrayRef]).unwrap();
795
796 let converted = convert_json_columns(&batch).unwrap();
798
799 assert_eq!(converted.num_columns(), 1);
801 let converted_schema = converted.schema();
802 let converted_field = converted_schema.field(0);
803 assert_eq!(converted_field.data_type(), &DataType::LargeBinary);
804 assert_eq!(
805 converted_field.metadata().get(ARROW_EXT_NAME_KEY),
806 Some(&JSON_EXT_NAME.to_string())
807 );
808
809 let converted_column = converted.column(0);
811 assert_eq!(converted_column.data_type(), &DataType::LargeBinary);
812 assert_eq!(converted_column.len(), 2);
813
814 let binary_array = converted_column
816 .as_any()
817 .downcast_ref::<LargeBinaryArray>()
818 .unwrap();
819 for i in 0..binary_array.len() {
820 let jsonb_bytes = binary_array.value(i);
821 let decoded = decode_json(jsonb_bytes);
822 assert!(decoded.contains("name"));
823 }
824 }
825
826 #[test]
827 fn test_convert_nested_json_columns() {
828 use arrow_buffer::{OffsetBuffer, ScalarBuffer};
829
830 let uri_field = Arc::new(ArrowField::new("uri", DataType::Utf8, false));
831 let mut metadata = std::collections::HashMap::new();
832 metadata.insert(
833 ARROW_EXT_NAME_KEY.to_string(),
834 ARROW_JSON_EXT_NAME.to_string(),
835 );
836 let extra_field =
837 Arc::new(ArrowField::new("extra", DataType::Utf8, true).with_metadata(metadata));
838 let item_fields = Fields::from(vec![uri_field, extra_field]);
839
840 let values = StructArray::new(
841 item_fields.clone(),
842 vec![
843 Arc::new(StringArray::from(vec![Some("a.jpg"), Some("b.jpg")])) as ArrayRef,
844 Arc::new(StringArray::from(vec![
845 Some(r#"{"codec":"h264"}"#),
846 None::<&str>,
847 ])) as ArrayRef,
848 ],
849 None,
850 );
851 let item = Arc::new(ArrowField::new("item", DataType::Struct(item_fields), true));
852 let media = ListArray::new(
853 item,
854 OffsetBuffer::new(ScalarBuffer::from(vec![0, 1, 2])),
855 Arc::new(values),
856 None,
857 );
858 let schema = Arc::new(Schema::new(vec![ArrowField::new(
859 "media",
860 media.data_type().clone(),
861 true,
862 )]));
863 let batch = RecordBatch::try_new(schema, vec![Arc::new(media) as ArrayRef]).unwrap();
864
865 assert!(has_arrow_json_fields(batch.schema().field(0)));
866
867 let converted = convert_json_columns(&batch).unwrap();
868 let converted_schema = converted.schema();
869 let DataType::List(item) = converted_schema.field(0).data_type() else {
870 panic!("expected list field");
871 };
872 let DataType::Struct(fields) = item.data_type() else {
873 panic!("expected struct item");
874 };
875 assert!(is_json_field(&fields[1]));
876
877 let list_array: &ListArray = converted.column(0).as_list();
878 let values = list_array.values().as_struct();
879 let extra = values
880 .column(1)
881 .as_any()
882 .downcast_ref::<LargeBinaryArray>()
883 .unwrap();
884 assert!(decode_json(extra.value(0)).contains("h264"));
885 assert!(extra.is_null(1));
886
887 let logical = convert_lance_json_to_arrow(&converted).unwrap();
888 let logical_schema = logical.schema();
889 let DataType::List(item) = logical_schema.field(0).data_type() else {
890 panic!("expected list field");
891 };
892 let DataType::Struct(fields) = item.data_type() else {
893 panic!("expected struct item");
894 };
895 assert!(is_arrow_json_field(&fields[1]));
896
897 let list_array: &ListArray = logical.column(0).as_list();
898 let values = list_array.values().as_struct();
899 let extra = values
900 .column(1)
901 .as_any()
902 .downcast_ref::<StringArray>()
903 .unwrap();
904 assert!(extra.value(0).contains("h264"));
905 assert!(extra.is_null(1));
906 }
907
908 #[test]
909 fn test_convert_fixed_size_list_zero_json_preserves_length() {
910 let mut metadata = std::collections::HashMap::new();
911 metadata.insert(
912 ARROW_EXT_NAME_KEY.to_string(),
913 ARROW_JSON_EXT_NAME.to_string(),
914 );
915 let item = Arc::new(ArrowField::new("item", DataType::Utf8, true).with_metadata(metadata));
916 let values = Arc::new(StringArray::from(Vec::<Option<&str>>::new())) as ArrayRef;
917 let lists = FixedSizeListArray::try_new_with_length(item, 0, values, None, 3).unwrap();
918 let schema = Arc::new(Schema::new(vec![ArrowField::new(
919 "lists",
920 lists.data_type().clone(),
921 true,
922 )]));
923 let batch = RecordBatch::try_new(schema, vec![Arc::new(lists) as ArrayRef]).unwrap();
924
925 let converted = convert_json_columns(&batch).unwrap();
926 assert_eq!(converted.num_rows(), 3);
927 assert_eq!(converted.column(0).len(), 3);
928
929 let converted_schema = converted.schema();
930 let DataType::FixedSizeList(item, size) = converted_schema.field(0).data_type() else {
931 panic!("expected fixed size list field");
932 };
933 assert_eq!(*size, 0);
934 assert!(is_json_field(item));
935
936 let logical = convert_lance_json_to_arrow(&converted).unwrap();
937 assert_eq!(logical.num_rows(), 3);
938 assert_eq!(logical.column(0).len(), 3);
939
940 let logical_schema = logical.schema();
941 let DataType::FixedSizeList(item, size) = logical_schema.field(0).data_type() else {
942 panic!("expected fixed size list field");
943 };
944 assert_eq!(*size, 0);
945 assert!(is_arrow_json_field(item));
946 }
947
948 #[test]
949 fn test_has_json_fields() {
950 let json_f = json_field("data", true);
952 assert!(has_json_fields(&json_f));
953
954 let non_json = ArrowField::new("data", DataType::Utf8, true);
956 assert!(!has_json_fields(&non_json));
957
958 let struct_field = ArrowField::new(
960 "struct",
961 DataType::Struct(vec![json_field("nested_json", true)].into()),
962 true,
963 );
964 assert!(has_json_fields(&struct_field));
965
966 let struct_no_json = ArrowField::new(
968 "struct",
969 DataType::Struct(vec![ArrowField::new("text", DataType::Utf8, true)].into()),
970 true,
971 );
972 assert!(!has_json_fields(&struct_no_json));
973
974 let list_field = ArrowField::new(
976 "list",
977 DataType::List(Arc::new(json_field("item", true))),
978 true,
979 );
980 assert!(has_json_fields(&list_field));
981
982 let large_list_field = ArrowField::new(
984 "large_list",
985 DataType::LargeList(Arc::new(json_field("item", true))),
986 true,
987 );
988 assert!(has_json_fields(&large_list_field));
989
990 let fixed_list_field = ArrowField::new(
992 "fixed_list",
993 DataType::FixedSizeList(Arc::new(json_field("item", true)), 3),
994 true,
995 );
996 assert!(has_json_fields(&fixed_list_field));
997
998 let map_field = ArrowField::new(
1000 "map",
1001 DataType::Map(
1002 Arc::new(ArrowField::new(
1003 "entries",
1004 DataType::Struct(
1005 vec![
1006 ArrowField::new("key", DataType::Utf8, false),
1007 json_field("value", true),
1008 ]
1009 .into(),
1010 ),
1011 false,
1012 )),
1013 false,
1014 ),
1015 true,
1016 );
1017 assert!(has_json_fields(&map_field));
1018 }
1019
1020 #[test]
1021 fn test_json_array_inner() {
1022 let json_array = JsonArray::try_from_iter(vec![Some(r#"{"a": 1}"#)]).unwrap();
1023 let inner = json_array.inner();
1024 assert_eq!(inner.len(), 1);
1025 }
1026
1027 #[test]
1028 fn test_json_array_value_null_error() {
1029 let json_array = JsonArray::try_from_iter(vec![None::<&str>]).unwrap();
1030 let result = json_array.value(0);
1031 assert!(result.is_err());
1032 assert!(result.unwrap_err().to_string().contains("null"));
1033 }
1034
1035 #[test]
1036 fn test_json_array_value_bytes() {
1037 let json_array = JsonArray::try_from_iter(vec![Some(r#"{"a": 1}"#)]).unwrap();
1038 let bytes = json_array.value_bytes(0);
1039 assert!(!bytes.is_empty());
1040 }
1041
1042 #[test]
1043 fn test_json_path_with_null() {
1044 let json_array =
1045 JsonArray::try_from_iter(vec![Some(r#"{"user": {"name": "Alice"}}"#), None::<&str>])
1046 .unwrap();
1047
1048 let result = json_array.json_path(1, "$.user.name").unwrap();
1049 assert_eq!(result, None);
1050 }
1051
1052 #[test]
1053 fn test_to_arrow_json() {
1054 let json_array = JsonArray::try_from_iter(vec![
1055 Some(r#"{"name": "Alice"}"#),
1056 None::<&str>,
1057 Some(r#"{"name": "Bob"}"#),
1058 ])
1059 .unwrap();
1060
1061 let arrow_json = json_array.to_arrow_json();
1062 assert_eq!(arrow_json.len(), 3);
1063 assert!(!arrow_json.is_null(0));
1064 assert!(arrow_json.is_null(1));
1065 assert!(!arrow_json.is_null(2));
1066
1067 let string_array = arrow_json.as_any().downcast_ref::<StringArray>().unwrap();
1068 assert!(string_array.value(0).contains("Alice"));
1069 assert!(string_array.value(2).contains("Bob"));
1070 }
1071
1072 #[test]
1073 fn test_json_array_trait_methods() {
1074 let json_array =
1075 JsonArray::try_from_iter(vec![Some(r#"{"a": 1}"#), Some(r#"{"b": 2}"#)]).unwrap();
1076
1077 assert_eq!(json_array.len(), 2);
1079 assert!(!json_array.is_empty());
1080 assert!(!json_array.is_null(0));
1081
1082 assert_eq!(json_array.inner().data_type(), &DataType::LargeBinary);
1084 assert_eq!(json_array.inner().len(), 2);
1085 }
1086
1087 #[test]
1088 fn test_json_array_empty() {
1089 let json_array = JsonArray::try_from_iter(Vec::<Option<&str>>::new()).unwrap();
1090 assert!(json_array.is_empty());
1091 assert_eq!(json_array.len(), 0);
1092 }
1093
1094 #[test]
1095 fn test_try_from_large_string_array() {
1096 let large_string_array = LargeStringArray::from(vec![
1097 Some(r#"{"name": "Alice"}"#),
1098 Some(r#"{"name": "Bob"}"#),
1099 None,
1100 ]);
1101
1102 let json_array = JsonArray::try_from(&large_string_array).unwrap();
1104 assert_eq!(json_array.len(), 3);
1105 assert!(!json_array.is_null(0));
1106 assert!(!json_array.is_null(1));
1107 assert!(json_array.is_null(2));
1108
1109 let large_string_array2 = LargeStringArray::from(vec![Some(r#"{"x": 1}"#)]);
1111 let json_array2 = JsonArray::try_from(large_string_array2).unwrap();
1112 assert_eq!(json_array2.len(), 1);
1113 }
1114
1115 #[test]
1116 fn test_try_from_array_ref() {
1117 let string_array: ArrayRef = Arc::new(StringArray::from(vec![
1119 Some(r#"{"a": 1}"#),
1120 Some(r#"{"b": 2}"#),
1121 ]));
1122 let json_array = JsonArray::try_from(string_array).unwrap();
1123 assert_eq!(json_array.len(), 2);
1124
1125 let large_string_array: ArrayRef = Arc::new(LargeStringArray::from(vec![
1127 Some(r#"{"c": 3}"#),
1128 Some(r#"{"d": 4}"#),
1129 ]));
1130 let json_array2 = JsonArray::try_from(large_string_array).unwrap();
1131 assert_eq!(json_array2.len(), 2);
1132
1133 let int_array: ArrayRef = Arc::new(arrow_array::Int32Array::from(vec![1, 2, 3]));
1135 let result = JsonArray::try_from(int_array);
1136 assert!(result.is_err());
1137 assert!(result.unwrap_err().to_string().contains("Unsupported"));
1138 }
1139
1140 #[test]
1141 fn test_arrow_json_to_lance_json_non_json_field() {
1142 let field = ArrowField::new("text", DataType::Utf8, true);
1144 let converted = arrow_json_to_lance_json(&field);
1145 assert_eq!(converted.data_type(), &DataType::Utf8);
1146 assert_eq!(converted.name(), "text");
1147 }
1148
1149 #[test]
1150 fn test_convert_lance_json_to_arrow() {
1151 let json_array = JsonArray::try_from_iter(vec![
1153 Some(r#"{"name": "Alice"}"#),
1154 None::<&str>,
1155 Some(r#"{"name": "Bob"}"#),
1156 ])
1157 .unwrap();
1158
1159 let lance_json_field = json_field("data", true);
1160 let schema = Arc::new(Schema::new(vec![lance_json_field]));
1161 let batch =
1162 RecordBatch::try_new(schema, vec![Arc::new(json_array.into_inner()) as ArrayRef])
1163 .unwrap();
1164
1165 let converted = convert_lance_json_to_arrow(&batch).unwrap();
1167
1168 let converted_schema = converted.schema();
1170 let converted_field = converted_schema.field(0);
1171 assert_eq!(converted_field.data_type(), &DataType::Utf8);
1172 assert_eq!(
1173 converted_field.metadata().get(ARROW_EXT_NAME_KEY),
1174 Some(&ARROW_JSON_EXT_NAME.to_string())
1175 );
1176
1177 let string_array = converted
1179 .column(0)
1180 .as_any()
1181 .downcast_ref::<StringArray>()
1182 .unwrap();
1183 assert!(!string_array.is_null(0));
1184 assert!(string_array.is_null(1));
1185 assert!(!string_array.is_null(2));
1186 assert!(string_array.value(0).contains("Alice"));
1187 assert!(string_array.value(2).contains("Bob"));
1188 }
1189
1190 #[test]
1191 fn test_convert_lance_json_to_arrow_empty_batch() {
1192 let lance_json_field = json_field("data", true);
1194 let schema = Arc::new(Schema::new(vec![lance_json_field]));
1195 let empty_binary = LargeBinaryBuilder::new().finish();
1196 let batch = RecordBatch::try_new(schema, vec![Arc::new(empty_binary) as ArrayRef]).unwrap();
1197
1198 let converted = convert_lance_json_to_arrow(&batch).unwrap();
1200 assert_eq!(converted.num_rows(), 0);
1201 assert_eq!(converted.schema().field(0).data_type(), &DataType::Utf8);
1202 }
1203
1204 #[test]
1205 fn test_convert_lance_json_to_arrow_no_json_columns() {
1206 let field = ArrowField::new("text", DataType::Utf8, true);
1208 let schema = Arc::new(Schema::new(vec![field]));
1209 let string_array = StringArray::from(vec![Some("hello"), Some("world")]);
1210 let batch = RecordBatch::try_new(schema, vec![Arc::new(string_array) as ArrayRef]).unwrap();
1211
1212 let converted = convert_lance_json_to_arrow(&batch).unwrap();
1214 assert_eq!(converted.num_columns(), 1);
1215 assert_eq!(converted.schema().field(0).data_type(), &DataType::Utf8);
1216 }
1217
1218 #[test]
1219 fn test_convert_json_columns_empty_batch() {
1220 let mut field = ArrowField::new("data", DataType::Utf8, false);
1222 let mut metadata = std::collections::HashMap::new();
1223 metadata.insert(
1224 ARROW_EXT_NAME_KEY.to_string(),
1225 ARROW_JSON_EXT_NAME.to_string(),
1226 );
1227 field.set_metadata(metadata);
1228
1229 let schema = Arc::new(Schema::new(vec![field]));
1230 let empty_strings = arrow_array::builder::StringBuilder::new().finish();
1231 let batch =
1232 RecordBatch::try_new(schema, vec![Arc::new(empty_strings) as ArrayRef]).unwrap();
1233
1234 let converted = convert_json_columns(&batch).unwrap();
1235 assert_eq!(converted.num_rows(), 0);
1236 assert_eq!(
1237 converted.schema().field(0).data_type(),
1238 &DataType::LargeBinary
1239 );
1240 }
1241
1242 #[test]
1243 fn test_convert_json_columns_large_string() {
1244 let json_strings = LargeStringArray::from(vec![
1246 Some(r#"{"name": "Alice"}"#),
1247 Some(r#"{"name": "Bob"}"#),
1248 ]);
1249
1250 let mut field = ArrowField::new("data", DataType::LargeUtf8, false);
1251 let mut metadata = std::collections::HashMap::new();
1252 metadata.insert(
1253 ARROW_EXT_NAME_KEY.to_string(),
1254 ARROW_JSON_EXT_NAME.to_string(),
1255 );
1256 field.set_metadata(metadata);
1257
1258 let schema = Arc::new(Schema::new(vec![field]));
1259 let batch = RecordBatch::try_new(schema, vec![Arc::new(json_strings) as ArrayRef]).unwrap();
1260
1261 let converted = convert_json_columns(&batch).unwrap();
1262 assert_eq!(converted.num_columns(), 1);
1263 assert_eq!(
1264 converted.schema().field(0).data_type(),
1265 &DataType::LargeBinary
1266 );
1267 assert_eq!(converted.num_rows(), 2);
1268 }
1269
1270 #[test]
1271 fn test_convert_json_columns_no_json_columns() {
1272 let field = ArrowField::new("text", DataType::Utf8, true);
1274 let schema = Arc::new(Schema::new(vec![field]));
1275 let string_array = StringArray::from(vec![Some("hello"), Some("world")]);
1276 let batch = RecordBatch::try_new(schema, vec![Arc::new(string_array) as ArrayRef]).unwrap();
1277
1278 let converted = convert_json_columns(&batch).unwrap();
1280 assert_eq!(converted.num_columns(), 1);
1281 assert_eq!(converted.schema().field(0).data_type(), &DataType::Utf8);
1282 }
1283
1284 #[test]
1285 fn test_convert_json_columns_mixed_columns() {
1286 let json_strings = StringArray::from(vec![
1288 Some(r#"{"name": "Alice"}"#),
1289 Some(r#"{"name": "Bob"}"#),
1290 ]);
1291 let text_strings = StringArray::from(vec![Some("hello"), Some("world")]);
1292
1293 let mut json_field = ArrowField::new("json_data", DataType::Utf8, false);
1294 let mut metadata = std::collections::HashMap::new();
1295 metadata.insert(
1296 ARROW_EXT_NAME_KEY.to_string(),
1297 ARROW_JSON_EXT_NAME.to_string(),
1298 );
1299 json_field.set_metadata(metadata);
1300
1301 let text_field = ArrowField::new("text_data", DataType::Utf8, true);
1302
1303 let schema = Arc::new(Schema::new(vec![json_field, text_field]));
1304 let batch = RecordBatch::try_new(
1305 schema,
1306 vec![
1307 Arc::new(json_strings) as ArrayRef,
1308 Arc::new(text_strings) as ArrayRef,
1309 ],
1310 )
1311 .unwrap();
1312
1313 let converted = convert_json_columns(&batch).unwrap();
1314 assert_eq!(converted.num_columns(), 2);
1315 assert_eq!(
1316 converted.schema().field(0).data_type(),
1317 &DataType::LargeBinary
1318 );
1319 assert_eq!(converted.schema().field(1).data_type(), &DataType::Utf8);
1320 }
1321
1322 #[test]
1323 fn test_is_arrow_json_field_large_utf8() {
1324 let mut field = ArrowField::new("data", DataType::LargeUtf8, true);
1326 let mut metadata = std::collections::HashMap::new();
1327 metadata.insert(
1328 ARROW_EXT_NAME_KEY.to_string(),
1329 ARROW_JSON_EXT_NAME.to_string(),
1330 );
1331 field.set_metadata(metadata);
1332
1333 assert!(is_arrow_json_field(&field));
1334 }
1335
1336 #[test]
1337 fn test_encode_json_invalid() {
1338 let result = encode_json("not valid json {");
1340 assert!(result.is_err());
1341 }
1342
1343 #[test]
1344 fn test_json_array_from_invalid_json() {
1345 let result = JsonArray::try_from_iter(vec![Some("invalid json {")]);
1347 assert!(result.is_err());
1348 assert!(result.unwrap_err().to_string().contains("Failed to encode"));
1349 }
1350
1351 #[test]
1352 fn test_try_from_string_array_invalid_json() {
1353 let string_array = StringArray::from(vec![Some("invalid json {")]);
1354 let result = JsonArray::try_from(string_array);
1355 assert!(result.is_err());
1356 }
1357
1358 #[test]
1359 fn test_try_from_large_string_array_invalid_json() {
1360 let large_string_array = LargeStringArray::from(vec![Some("invalid json {")]);
1361 let result = JsonArray::try_from(large_string_array);
1362 assert!(result.is_err());
1363 }
1364
1365 #[test]
1366 fn test_convert_lance_json_to_arrow_mixed_columns() {
1367 let json_array = JsonArray::try_from_iter(vec![
1369 Some(r#"{"name": "Alice"}"#),
1370 Some(r#"{"name": "Bob"}"#),
1371 ])
1372 .unwrap();
1373 let text_strings = StringArray::from(vec![Some("hello"), Some("world")]);
1374
1375 let json_f = json_field("json_data", true);
1376 let text_field = ArrowField::new("text_data", DataType::Utf8, true);
1377
1378 let schema = Arc::new(Schema::new(vec![json_f, text_field]));
1379 let batch = RecordBatch::try_new(
1380 schema,
1381 vec![
1382 Arc::new(json_array.into_inner()) as ArrayRef,
1383 Arc::new(text_strings) as ArrayRef,
1384 ],
1385 )
1386 .unwrap();
1387
1388 let converted = convert_lance_json_to_arrow(&batch).unwrap();
1389 assert_eq!(converted.num_columns(), 2);
1390 assert_eq!(converted.schema().field(0).data_type(), &DataType::Utf8);
1391 assert_eq!(converted.schema().field(1).data_type(), &DataType::Utf8);
1392 }
1393
1394 #[test]
1395 fn test_json_path_invalid_path() {
1396 let json_array = JsonArray::try_from_iter(vec![Some(r#"{"a": 1}"#)]).unwrap();
1397 let result = json_array.json_path(0, "invalid path without $");
1399 assert!(result.is_err());
1400 assert!(result.unwrap_err().to_string().contains("Invalid JSONPath"));
1401 }
1402
1403 #[test]
1404 fn test_convert_json_columns_invalid_storage_type() {
1405 let int_array = arrow_array::Int32Array::from(vec![1, 2, 3]);
1407
1408 let mut field = ArrowField::new("data", DataType::Int32, false);
1409 let mut metadata = std::collections::HashMap::new();
1410 metadata.insert(
1411 ARROW_EXT_NAME_KEY.to_string(),
1412 ARROW_JSON_EXT_NAME.to_string(),
1413 );
1414 field.set_metadata(metadata);
1415
1416 let schema = Arc::new(Schema::new(vec![field]));
1417 let batch = RecordBatch::try_new(schema, vec![Arc::new(int_array) as ArrayRef]).unwrap();
1418
1419 let result = convert_json_columns(&batch);
1422 assert!(result.is_ok());
1423 }
1424
1425 #[test]
1426 fn test_is_json_field_wrong_extension() {
1427 let field = ArrowField::new("data", DataType::LargeBinary, true);
1429 assert!(!is_json_field(&field));
1430
1431 let mut field2 = ArrowField::new("data", DataType::LargeBinary, true);
1433 let mut metadata = std::collections::HashMap::new();
1434 metadata.insert(
1435 ARROW_EXT_NAME_KEY.to_string(),
1436 "other.extension".to_string(),
1437 );
1438 field2.set_metadata(metadata);
1439 assert!(!is_json_field(&field2));
1440 }
1441
1442 #[test]
1443 fn test_is_arrow_json_field_wrong_extension() {
1444 let field = ArrowField::new("data", DataType::Utf8, true);
1446 assert!(!is_arrow_json_field(&field));
1447
1448 let mut field2 = ArrowField::new("data", DataType::Utf8, true);
1450 let mut metadata = std::collections::HashMap::new();
1451 metadata.insert(
1452 ARROW_EXT_NAME_KEY.to_string(),
1453 "other.extension".to_string(),
1454 );
1455 field2.set_metadata(metadata);
1456 assert!(!is_arrow_json_field(&field2));
1457
1458 let field3 = ArrowField::new("data", DataType::Int32, true);
1460 assert!(!is_arrow_json_field(&field3));
1461 }
1462
1463 #[test]
1464 fn test_convert_json_columns_invalid_json_utf8() {
1465 let invalid_json = StringArray::from(vec![Some("invalid json {")]);
1467
1468 let mut field = ArrowField::new("data", DataType::Utf8, false);
1469 let mut metadata = std::collections::HashMap::new();
1470 metadata.insert(
1471 ARROW_EXT_NAME_KEY.to_string(),
1472 ARROW_JSON_EXT_NAME.to_string(),
1473 );
1474 field.set_metadata(metadata);
1475
1476 let schema = Arc::new(Schema::new(vec![field]));
1477 let batch = RecordBatch::try_new(schema, vec![Arc::new(invalid_json) as ArrayRef]).unwrap();
1478
1479 let result = convert_json_columns(&batch);
1480 assert!(result.is_err());
1481 }
1482
1483 #[test]
1484 fn test_convert_json_columns_invalid_json_large_utf8() {
1485 let invalid_json = LargeStringArray::from(vec![Some("invalid json {")]);
1487
1488 let mut field = ArrowField::new("data", DataType::LargeUtf8, false);
1489 let mut metadata = std::collections::HashMap::new();
1490 metadata.insert(
1491 ARROW_EXT_NAME_KEY.to_string(),
1492 ARROW_JSON_EXT_NAME.to_string(),
1493 );
1494 field.set_metadata(metadata);
1495
1496 let schema = Arc::new(Schema::new(vec![field]));
1497 let batch = RecordBatch::try_new(schema, vec![Arc::new(invalid_json) as ArrayRef]).unwrap();
1498
1499 let result = convert_json_columns(&batch);
1500 assert!(result.is_err());
1501 }
1502
1503 #[test]
1504 fn test_json_path_on_corrupted_jsonb() {
1505 let corrupted_bytes: &[u8] = &[0xFF, 0xFE, 0x00, 0x01, 0x02];
1507 let corrupted_binary = LargeBinaryArray::from(vec![Some(corrupted_bytes)]);
1508
1509 let corrupted_json = JsonArray {
1511 inner: corrupted_binary,
1512 };
1513
1514 let _result = corrupted_json.json_path(0, "$.a");
1517 }
1519
1520 #[test]
1521 fn test_decode_json_on_various_inputs() {
1522 let valid_jsonb = encode_json(r#"{"key": "value"}"#).unwrap();
1524 let decoded = decode_json(&valid_jsonb);
1525 assert!(decoded.contains("key"));
1526
1527 let decoded_empty = decode_json(&[]);
1529 let _ = decoded_empty;
1531
1532 let decoded_random = decode_json(&[0xFF, 0xFE, 0x00]);
1534 let _ = decoded_random;
1536 }
1537}