1use std::any::Any;
16use std::collections::{BTreeMap, HashMap};
17use std::sync::Arc;
18
19use arrow_array::cast::AsArray;
20use arrow_array::{Array, ArrayRef, StructArray};
21use arrow_schema::DataType;
22use parquet_variant_compute::VariantArrayBuilder;
23use snafu::{ResultExt, ensure};
24
25use crate::data_type::ConcreteDataType;
26use crate::error::{
27 ArrowComputeSnafu, Result, TryFromValueSnafu, UnexpectedSnafu, UnimplementedSnafu,
28 UnsupportedOperationSnafu,
29};
30use crate::extension::json::JSON2_REMAINDER_FIELD_NAME;
31use crate::json::value::{JsonNumber, JsonVariant, JsonVariantRef, encode_json_variant};
32use crate::json::{
33 JSON2_DEFAULT_MAX_AUTO_EXPANDED_PATHS, JSON2_MAX_STRUCTURED_DEPTH, JsonSettings,
34};
35use crate::prelude::{ValueRef, Vector, VectorRef};
36use crate::types::StructType;
37use crate::types::json_type::{JsonNativeType, is_include};
38use crate::value::{ListValue, ListValueRef, StructValue, StructValueRef, Value};
39use crate::vectors::json::variant::{append_json_variant, append_json_variant_ref, variant_field};
40use crate::vectors::{Helper, MutableVector, NullVector, StructVectorBuilder};
41
42type JsonObjectValue = BTreeMap<String, JsonVariant>;
43
44pub(crate) struct JsonVectorBuilder {
51 state: JsonVectorBuilderState,
52}
53
54enum JsonVectorBuilderState {
55 Legacy {
56 merged_type: JsonNativeType,
57 values: Vec<JsonVariant>,
58 },
59 ExplicitOnly {
60 explicit_type: JsonNativeType,
62 struct_type: StructType,
64 explicit: StructVectorBuilder,
66 remainder: VariantArrayBuilder,
68 },
69 AutoExpanding {
70 explicit_type: JsonNativeType,
72 max_auto_expanded_paths: u32,
74 values: Vec<JsonVariant>,
76 },
77}
78
79impl JsonVectorBuilderState {
80 fn native_type(&self) -> JsonNativeType {
81 match self {
82 Self::Legacy { merged_type, .. } => merged_type.clone(),
83 Self::ExplicitOnly { explicit_type, .. } => explicit_type.clone(),
84 Self::AutoExpanding {
85 explicit_type,
86 max_auto_expanded_paths,
87 values,
88 } => infer_expanded_type(explicit_type, *max_auto_expanded_paths, values),
89 }
90 }
91
92 fn len(&self) -> usize {
93 match self {
94 Self::Legacy { values, .. } | Self::AutoExpanding { values, .. } => values.len(),
95 Self::ExplicitOnly { explicit, .. } => explicit.len(),
96 }
97 }
98
99 fn try_build(&mut self) -> Result<VectorRef> {
100 match self {
101 Self::Legacy {
102 merged_type,
103 values,
104 } => build_legacy(values, merged_type),
105 Self::ExplicitOnly {
106 explicit,
107 remainder,
108 ..
109 } => {
110 let remainder = std::mem::replace(remainder, VariantArrayBuilder::new(0)).build();
111 finish_vector(explicit.to_vector(), ArrayRef::from(remainder))
112 }
113 Self::AutoExpanding {
114 explicit_type,
115 max_auto_expanded_paths,
116 values,
117 } => {
118 let expanded_type =
119 infer_expanded_type(explicit_type, *max_auto_expanded_paths, values);
120 build_with_remainder(values, &expanded_type)
121 }
122 }
123 }
124
125 fn try_build_cloned(&self) -> Result<VectorRef> {
126 let mut state = match self {
127 Self::Legacy {
128 merged_type,
129 values,
130 } => Self::Legacy {
131 merged_type: merged_type.clone(),
132 values: values.clone(),
133 },
134 Self::AutoExpanding {
135 explicit_type,
136 max_auto_expanded_paths,
137 values,
138 } => Self::AutoExpanding {
139 explicit_type: explicit_type.clone(),
140 max_auto_expanded_paths: *max_auto_expanded_paths,
141 values: values.clone(),
142 },
143 Self::ExplicitOnly { .. } => {
148 return UnimplementedSnafu {
149 feat: "no auto expanded JSON2 array builder",
150 }
151 .fail();
152 }
153 };
154 state.try_build()
155 }
156
157 fn try_push_value_ref(&mut self, value: &ValueRef) -> Result<()> {
158 let ValueRef::Json(value) = value else {
159 return TryFromValueSnafu {
160 reason: format!("expected JSON value, got {value:?}"),
161 }
162 .fail();
163 };
164 ensure!(
165 value.is_object() || value.is_null(),
166 TryFromValueSnafu {
167 reason: format!("expected JSON object value, got {value:?}"),
168 }
169 );
170 match self {
171 Self::Legacy {
172 merged_type,
173 values,
174 } => {
175 let json_type = value.json_type();
176 if !is_include(merged_type, json_type.as_ref()) {
177 merged_type.merge(json_type.as_ref());
178 }
179 values.push(JsonVariant::from(value.variant()));
180 }
181 Self::ExplicitOnly {
182 explicit_type,
183 struct_type,
184 explicit,
185 remainder,
186 } => {
187 if value.is_null() {
188 explicit.push_null();
189 remainder.append_null();
190 } else {
191 let (value, rest) =
192 split_to_explicit_ref(value.variant(), explicit_type, struct_type)?;
193 explicit.push_struct_value_ref(value)?;
194 append_json_variant_ref(remainder, &rest).context(ArrowComputeSnafu)?;
195 }
196 }
197 Self::AutoExpanding { values, .. } => {
198 values.push(JsonVariant::from(value.variant()));
199 }
200 }
201 Ok(())
202 }
203
204 fn push_null(&mut self) {
205 match self {
206 Self::Legacy { values, .. } | Self::AutoExpanding { values, .. } => {
207 values.push(JsonVariant::Null)
208 }
209 Self::ExplicitOnly {
210 explicit,
211 remainder,
212 ..
213 } => {
214 explicit.push_null();
215 remainder.append_null();
216 }
217 }
218 }
219}
220
221pub fn json2_physical_data_type(settings: &JsonSettings) -> DataType {
223 let DataType::Struct(fields) = explicit_type(settings).as_arrow_type() else {
224 unreachable!("JSON2 explicit type must map to Arrow Struct")
225 };
226 let mut fields = fields
227 .iter()
228 .cloned()
229 .chain(std::iter::once(Arc::new(variant_field(
230 JSON2_REMAINDER_FIELD_NAME,
231 true,
232 ))))
233 .collect::<Vec<_>>();
234 fields.sort_unstable_by(|x, y| x.name().cmp(y.name()));
235 DataType::Struct(fields.into())
236}
237
238fn explicit_type(settings: &JsonSettings) -> JsonNativeType {
239 let mut explicit_type = JsonNativeType::Object(Default::default());
240 for hint in settings.type_hints() {
241 insert_dynamic_type(&mut explicit_type, &hint.path, (&hint.data_type).into());
242 }
243 explicit_type
244}
245
246impl JsonVectorBuilder {
247 pub(crate) fn new(initial_native_type: JsonNativeType, capacity: usize) -> Self {
249 debug_assert!(matches!(
250 initial_native_type,
251 JsonNativeType::Object(_) | JsonNativeType::Null
252 ));
253 Self {
254 state: JsonVectorBuilderState::Legacy {
255 merged_type: initial_native_type,
256 values: Vec::with_capacity(capacity),
257 },
258 }
259 }
260
261 pub(crate) fn with_settings(settings: &JsonSettings, capacity: usize) -> Self {
263 let explicit_type = explicit_type(settings);
264 let state = if settings.max_auto_expanded_paths() == Some(0) {
265 let DataType::Struct(fields) = explicit_type.as_arrow_type() else {
266 unreachable!("JSON2 explicit type must map to Arrow Struct")
267 };
268 let struct_type = StructType::from(&fields);
269 JsonVectorBuilderState::ExplicitOnly {
270 explicit_type,
271 explicit: StructVectorBuilder::with_type_and_capacity(
272 struct_type.clone(),
273 capacity,
274 ),
275 struct_type,
276 remainder: VariantArrayBuilder::new(capacity),
277 }
278 } else {
279 JsonVectorBuilderState::AutoExpanding {
280 explicit_type,
281 max_auto_expanded_paths: settings
282 .max_auto_expanded_paths()
283 .unwrap_or(JSON2_DEFAULT_MAX_AUTO_EXPANDED_PATHS),
284 values: Vec::with_capacity(capacity),
285 }
286 };
287 Self { state }
288 }
289
290 fn try_build(&mut self) -> Result<VectorRef> {
291 self.state.try_build()
292 }
293}
294
295fn build_legacy(values: &mut Vec<JsonVariant>, merged_type: &JsonNativeType) -> Result<VectorRef> {
296 build_explicit(values, merged_type, false, |value| match value {
297 JsonVariant::Null => Ok(None),
298 JsonVariant::Object(value) => Ok(Some(value)),
299 _ => TryFromValueSnafu {
300 reason: "expected json object value".to_string(),
301 }
302 .fail(),
303 })
304}
305
306fn build_with_remainder(
307 values: &mut Vec<JsonVariant>,
308 expanded_type: &JsonNativeType,
309) -> Result<VectorRef> {
310 let mut remainder = VariantArrayBuilder::new(values.len());
311 let explicit = build_explicit(values, expanded_type, true, |value| {
312 if matches!(value, JsonVariant::Null) {
313 remainder.append_null();
314 return Ok(None);
315 }
316 let (value, rest) = split_to_explicit(value, expanded_type)?;
317 append_json_variant(&mut remainder, &JsonVariant::Object(rest))
318 .context(ArrowComputeSnafu)?;
319 Ok(Some(value))
320 })?;
321 finish_vector(explicit, ArrayRef::from(remainder.build()))
322}
323
324fn build_explicit(
325 values: &mut Vec<JsonVariant>,
326 explicit_type: &JsonNativeType,
327 preserve_empty_structs: bool,
330 mut project: impl FnMut(JsonVariant) -> Result<Option<JsonObjectValue>>,
331) -> Result<VectorRef> {
332 let DataType::Struct(fields) = explicit_type.as_arrow_type() else {
333 return UnexpectedSnafu {
334 reason: "merged JSON2 type must map to Arrow Struct in JsonVectorBuilder",
335 }
336 .fail();
337 };
338 let struct_type = StructType::from(&fields);
340
341 let mut builder =
342 StructVectorBuilder::with_type_and_capacity(struct_type.clone(), values.len());
343 for value in std::mem::take(values) {
344 let Some(value) = project(value)? else {
345 builder.push_null();
346 continue;
347 };
348 let value =
349 json_variant_into_struct_value(value, struct_type.clone(), preserve_empty_structs)?;
350 builder.push_struct_value_ref(StructValueRef::Ref(&value))?;
351 }
352 Ok(builder.to_vector())
353}
354
355fn finish_vector(explicit: VectorRef, remainder: ArrayRef) -> Result<VectorRef> {
356 let explicit = explicit.to_arrow_array();
357 let explicit = explicit.as_struct();
358 let mut children = explicit
359 .fields()
360 .iter()
361 .cloned()
362 .zip(explicit.columns().iter().cloned())
363 .chain(std::iter::once((
364 Arc::new(variant_field(JSON2_REMAINDER_FIELD_NAME, true)),
365 remainder,
366 )))
367 .collect::<Vec<_>>();
368 children.sort_unstable_by(|(x, _), (y, _)| x.name().cmp(y.name()));
369 let (fields, columns): (Vec<_>, Vec<ArrayRef>) = children.into_iter().unzip();
370 let array: ArrayRef = Arc::new(StructArray::new(
371 fields.into(),
372 columns,
373 explicit.nulls().cloned(),
374 ));
375 Helper::try_into_vector(array)
376}
377
378fn infer_expanded_type(
379 explicit_type: &JsonNativeType,
380 max_auto_expanded_paths: u32,
381 values: &[JsonVariant],
382) -> JsonNativeType {
383 if max_auto_expanded_paths == 0 {
384 return explicit_type.clone();
385 }
386
387 let mut stats = HashMap::new();
388 let mut path = Vec::new();
389 init_explicit_path_stats(explicit_type, &mut path, &mut stats);
390 for value in values {
391 count_dynamic_paths(value, &mut path, &mut stats);
392 }
393 let mut candidates = stats
394 .iter()
395 .filter(|(_, stat)| !stat.is_explicit && stat.is_leaf)
398 .filter(|(path, _)| {
401 !(1..=path.len())
402 .any(|len| stats.get(&path[..len]).is_some_and(|stats| stats.conflicts))
403 })
404 .collect::<Vec<_>>();
405 candidates.sort_unstable_by(|(x_path, x), (y_path, y)| {
406 y.seen_count
407 .cmp(&x.seen_count)
408 .then_with(|| x_path.cmp(y_path))
409 });
410
411 let mut expanded_type = explicit_type.clone();
412 for (path, candidate) in candidates
413 .into_iter()
414 .take(max_auto_expanded_paths as usize)
415 {
416 insert_dynamic_type(
417 &mut expanded_type,
418 path,
419 candidate.expected_leaf_type.clone(),
420 );
421 }
422 expanded_type
423}
424
425struct PathStats {
437 is_explicit: bool,
439 is_leaf: bool,
441 expected_leaf_type: JsonNativeType,
443 seen_count: usize,
445 conflicts: bool,
447}
448
449fn init_explicit_path_stats<'a>(
451 explicit_type: &'a JsonNativeType,
452 path: &mut Vec<&'a str>,
453 stats: &mut HashMap<Vec<&'a str>, PathStats>,
454) {
455 let JsonNativeType::Object(fields) = explicit_type else {
456 return;
457 };
458 for (name, data_type) in fields {
459 path.push(name);
460 let is_leaf = !matches!(data_type, JsonNativeType::Object(_));
461 let expected_leaf_type = if is_leaf {
462 data_type.clone()
463 } else {
464 JsonNativeType::default()
465 };
466 stats.insert(
467 path.clone(),
468 PathStats {
469 is_explicit: true,
470 is_leaf,
471 expected_leaf_type,
472 seen_count: 0,
473 conflicts: false,
474 },
475 );
476 init_explicit_path_stats(data_type, path, stats);
477 path.pop();
478 }
479}
480
481fn count_dynamic_paths<'a>(
483 value: &'a JsonVariant,
484 path: &mut Vec<&'a str>,
485 stats: &mut HashMap<Vec<&'a str>, PathStats>,
486) {
487 if matches!(value, JsonVariant::Null) || path.len() > JSON2_MAX_STRUCTURED_DEPTH {
488 return;
489 }
490
491 if !path.is_empty() {
492 let is_leaf = !matches!(value, JsonVariant::Object(_));
493 let conflicts = if let Some(stats) = stats.get_mut(path.as_slice()) {
494 if !stats.conflicts {
495 let role_conflict = stats.is_leaf != is_leaf;
496 let type_conflict = || match (&stats.expected_leaf_type, value) {
497 (JsonNativeType::Null | JsonNativeType::Object(_), JsonVariant::Object(_)) => {
499 false
500 }
501 _ => stats.expected_leaf_type != value.native_type(),
502 };
503 if role_conflict || type_conflict() {
504 stats.conflicts = true;
505 } else {
506 stats.seen_count += 1;
507 }
508 }
509 stats.conflicts
510 } else {
511 let expected_leaf_type = if is_leaf {
512 value.native_type()
513 } else {
514 JsonNativeType::default()
515 };
516 stats.insert(
517 path.clone(),
518 PathStats {
519 is_explicit: false,
520 is_leaf,
521 expected_leaf_type,
522 seen_count: 1,
523 conflicts: false,
524 },
525 );
526 false
527 };
528 if conflicts {
529 return;
530 }
531 }
532
533 if let JsonVariant::Object(object) = value
534 && !object.is_empty()
535 {
536 for (name, value) in object {
537 path.push(name);
538 count_dynamic_paths(value, path, stats);
539 path.pop();
540 }
541 }
542}
543
544fn insert_dynamic_type<S: AsRef<str>>(
545 explicit_type: &mut JsonNativeType,
546 path: &[S],
547 data_type: JsonNativeType,
548) {
549 let JsonNativeType::Object(fields) = explicit_type else {
550 return;
551 };
552 let Some((name, path)) = path.split_first() else {
553 return;
554 };
555 let name = name.as_ref().to_string();
556 if path.is_empty() {
557 fields.insert(name, data_type);
558 return;
559 }
560 insert_dynamic_type(
561 fields
562 .entry(name)
563 .or_insert_with(|| JsonNativeType::Object(Default::default())),
564 path,
565 data_type,
566 )
567}
568
569fn split_to_explicit_ref<'a>(
570 value: &JsonVariantRef<'a>,
571 explicit_type: &JsonNativeType,
572 struct_type: &StructType,
573) -> Result<(StructValueRef<'a>, JsonVariantRef<'a>)> {
574 let JsonVariantRef::Object(object) = value else {
575 return TryFromValueSnafu {
576 reason: "expected json object value".to_string(),
577 }
578 .fail();
579 };
580 let explicit = json_object_ref_into_struct_value_ref(object, struct_type)?;
581 let remainder = remainder_ref(object, explicit_type)?;
582 Ok((explicit, JsonVariantRef::Object(remainder)))
583}
584
585fn json_object_ref_into_struct_value_ref<'a>(
586 object: &BTreeMap<&'a str, JsonVariantRef<'a>>,
587 struct_type: &StructType,
588) -> Result<StructValueRef<'a>> {
589 let mut values = Vec::with_capacity(struct_type.fields().len());
590 for field in struct_type.fields().iter() {
591 let value = match object.get(field.name()) {
592 Some(value) => json_variant_ref_into_value_ref(value, field.data_type())?,
593 None => ValueRef::Null,
594 };
595 values.push(value);
596 }
597 Ok(StructValueRef::RefList {
598 val: values,
599 fields: struct_type.clone(),
600 })
601}
602
603fn json_variant_ref_into_value_ref<'a>(
604 value: &JsonVariantRef<'a>,
605 expected_type: &ConcreteDataType,
606) -> Result<ValueRef<'a>> {
607 let value = match (value, expected_type) {
608 (JsonVariantRef::Null, _) | (_, ConcreteDataType::Null(_)) => ValueRef::Null,
609 (JsonVariantRef::Object(object), ConcreteDataType::Struct(struct_type)) => {
610 ValueRef::Struct(json_object_ref_into_struct_value_ref(object, struct_type)?)
611 }
612 (JsonVariantRef::Bool(x), ConcreteDataType::Boolean(_)) => ValueRef::Boolean(*x),
613 (JsonVariantRef::Number(x), ConcreteDataType::UInt64(_)) => {
614 let Some(x) = x.as_u64() else {
615 return TryFromValueSnafu {
616 reason: format!("unable to convert {x:?} to UInt64"),
617 }
618 .fail();
619 };
620 ValueRef::UInt64(x)
621 }
622 (JsonVariantRef::Number(x), ConcreteDataType::Int64(_)) => {
623 let x = match x {
624 JsonNumber::PosInt(x) => i64::try_from(*x).ok(),
625 JsonNumber::NegInt(x) => Some(*x),
626 JsonNumber::Float(_) => None,
627 };
628 let Some(x) = x else {
629 return TryFromValueSnafu {
630 reason: format!("unable to convert {x:?} to Int64"),
631 }
632 .fail();
633 };
634 ValueRef::Int64(x)
635 }
636 (JsonVariantRef::Number(JsonNumber::PosInt(x)), ConcreteDataType::Float64(_)) => {
637 ValueRef::Float64((*x as f64).into())
638 }
639 (JsonVariantRef::Number(JsonNumber::NegInt(x)), ConcreteDataType::Float64(_)) => {
640 ValueRef::Float64((*x as f64).into())
641 }
642 (JsonVariantRef::Number(JsonNumber::Float(x)), ConcreteDataType::Float64(_)) => {
643 ValueRef::Float64(*x)
644 }
645 (JsonVariantRef::String(x), ConcreteDataType::String(_)) => ValueRef::String(x),
646 (JsonVariantRef::Array(array), ConcreteDataType::List(list_type)) => {
647 let item_type = list_type.item_type().clone();
648 let values = array
649 .iter()
650 .map(|x| json_variant_ref_into_value_ref(x, &item_type))
651 .collect::<Result<Vec<_>>>()?;
652 ValueRef::List(ListValueRef::RefList {
653 val: values,
654 item_datatype: Arc::new(item_type),
655 })
656 }
657 (value, expected_type) => {
658 return TryFromValueSnafu {
659 reason: format!("unable to convert json value {value:?} to {expected_type}"),
660 }
661 .fail();
662 }
663 };
664 Ok(value)
665}
666
667fn remainder_ref<'a>(
668 object: &BTreeMap<&'a str, JsonVariantRef<'a>>,
669 explicit_type: &JsonNativeType,
670) -> Result<BTreeMap<&'a str, JsonVariantRef<'a>>> {
671 let JsonNativeType::Object(fields) = explicit_type else {
672 return UnexpectedSnafu {
673 reason: "JSON2 explicit type must be an object",
674 }
675 .fail();
676 };
677 let mut remainder = BTreeMap::new();
678 for (&name, value) in object {
679 if *value == JsonVariantRef::Null {
682 remainder.insert(name, JsonVariantRef::Null);
683 continue;
684 }
685
686 match fields.get(name) {
687 Some(data_type @ JsonNativeType::Object(_)) => match value {
688 JsonVariantRef::Object(object) => {
689 let child = remainder_ref(object, data_type)?;
690 if !child.is_empty() {
691 remainder.insert(name, JsonVariantRef::Object(child));
692 }
693 }
694 _ => {
695 return TryFromValueSnafu {
696 reason: "expected json object value".to_string(),
697 }
698 .fail();
699 }
700 },
701 Some(_) => {}
704 None => {
705 remainder.insert(name, value.clone());
706 }
707 }
708 }
709 Ok(remainder)
710}
711
712fn split_to_explicit(
713 value: JsonVariant,
714 explicit_type: &JsonNativeType,
715) -> Result<(JsonObjectValue, JsonObjectValue)> {
716 let JsonVariant::Object(mut remainder) = value else {
717 return TryFromValueSnafu {
718 reason: "expected json object value".to_string(),
719 }
720 .fail();
721 };
722 let JsonNativeType::Object(fields) = explicit_type else {
723 return UnexpectedSnafu {
724 reason: "JSON2 explicit type must be an object",
725 }
726 .fail();
727 };
728 let mut explicit = JsonObjectValue::new();
729
730 for (name, data_type) in fields {
731 let Some(value) = remainder.remove(name) else {
732 continue;
733 };
734 if value == JsonVariant::Null {
735 explicit.insert(name.clone(), JsonVariant::Null);
736 remainder.insert(name.clone(), JsonVariant::Null);
739 continue;
740 }
741 if matches!(data_type, JsonNativeType::Object(_)) {
742 let (child_explicit, child_remainder) = split_to_explicit(value, data_type)?;
743 explicit.insert(name.clone(), JsonVariant::Object(child_explicit));
744 if !child_remainder.is_empty() {
745 remainder.insert(name.clone(), JsonVariant::Object(child_remainder));
746 }
747 } else {
748 explicit.insert(name.clone(), value);
749 }
750 }
751 Ok((explicit, remainder))
752}
753
754fn json_variant_into_struct_value(
755 object: JsonObjectValue,
756 struct_type: StructType,
757 preserve_empty_structs: bool,
758) -> Result<StructValue> {
759 let mut entries = object.into_iter();
760 let mut entry = entries.next();
761 let mut values = Vec::with_capacity(struct_type.fields().len());
762 for field in struct_type.fields().iter() {
763 let value = match entry.take() {
764 Some((name, value)) if name == field.name() => {
765 entry = entries.next();
766 json_variant_into_value(value, field.data_type(), preserve_empty_structs)?
767 }
768 Some((name, _)) if name.as_str() < field.name() => {
769 return TryFromValueSnafu {
770 reason: format!("field {name} is missing from merged JSON type"),
771 }
772 .fail();
773 }
774 next => {
775 entry = next;
776 Value::Null
777 }
778 };
779 values.push(value);
780 }
781 if let Some((name, _)) = entry {
782 return TryFromValueSnafu {
783 reason: format!("field {name} is missing from merged JSON type"),
784 }
785 .fail();
786 }
787
788 Ok(StructValue::new(values, struct_type))
789}
790
791fn json_variant_into_value(
792 value: JsonVariant,
793 expected_type: &ConcreteDataType,
794 preserve_empty_structs: bool,
795) -> Result<Value> {
796 let value = match (value, expected_type) {
797 (JsonVariant::Null, _) | (_, ConcreteDataType::Null(_)) => Value::Null,
798 (JsonVariant::Object(object), _) if object.is_empty() && !preserve_empty_structs => {
799 Value::Null
800 }
801 (JsonVariant::Object(object), ConcreteDataType::Struct(struct_type)) => Value::Struct(
802 json_variant_into_struct_value(object, struct_type.clone(), preserve_empty_structs)?,
803 ),
804 (JsonVariant::Bool(x), ConcreteDataType::Boolean(_)) => Value::Boolean(x),
805 (JsonVariant::Number(x), ConcreteDataType::UInt64(_)) => {
806 let Some(x) = x.as_u64() else {
807 return TryFromValueSnafu {
808 reason: format!("unable to convert {x:?} to UInt64"),
809 }
810 .fail();
811 };
812 Value::UInt64(x)
813 }
814 (JsonVariant::Number(x), ConcreteDataType::Int64(_)) => {
815 let x = match x {
816 JsonNumber::PosInt(x) => i64::try_from(x).ok(),
817 JsonNumber::NegInt(x) => Some(x),
818 JsonNumber::Float(_) => None,
819 };
820 let Some(x) = x else {
821 return TryFromValueSnafu {
822 reason: format!("unable to convert {x:?} to Int64"),
823 }
824 .fail();
825 };
826 Value::Int64(x)
827 }
828 (JsonVariant::Number(JsonNumber::PosInt(x)), ConcreteDataType::Float64(_)) => {
829 Value::Float64((x as f64).into())
830 }
831 (JsonVariant::Number(JsonNumber::NegInt(x)), ConcreteDataType::Float64(_)) => {
832 Value::Float64((x as f64).into())
833 }
834 (JsonVariant::Number(JsonNumber::Float(x)), ConcreteDataType::Float64(_)) => {
835 Value::Float64(x)
836 }
837 (JsonVariant::String(x), ConcreteDataType::String(_)) => Value::String(x.into()),
838 (JsonVariant::Array(array), ConcreteDataType::List(list_type)) => {
839 let item_type = list_type.item_type().clone();
840 let values = array
841 .into_iter()
842 .map(|v| json_variant_into_value(v, &item_type, preserve_empty_structs))
843 .collect::<Result<Vec<_>>>()?;
844 Value::List(ListValue::new(values, Arc::new(item_type)))
845 }
846 (value, ConcreteDataType::Binary(_)) => Value::from(encode_json_variant(value)?),
847 (value, expected_type) => {
848 return TryFromValueSnafu {
849 reason: format!("unable to convert json value {value:?} to {expected_type}"),
850 }
851 .fail();
852 }
853 };
854 Ok(value)
855}
856
857impl MutableVector for JsonVectorBuilder {
858 fn data_type(&self) -> ConcreteDataType {
859 ConcreteDataType::json2(self.state.native_type())
860 }
861
862 fn len(&self) -> usize {
863 self.state.len()
864 }
865
866 fn as_any(&self) -> &dyn Any {
867 self
868 }
869
870 fn as_mut_any(&mut self) -> &mut dyn Any {
871 self
872 }
873
874 fn to_vector(&mut self) -> VectorRef {
875 self.try_build().unwrap_or_else(|e| {
876 common_telemetry::error!(e; "Unable to build JSON2 vector");
878 Arc::new(NullVector::new(self.len()))
879 })
880 }
881
882 fn to_vector_cloned(&self) -> VectorRef {
883 self.state.try_build_cloned().unwrap_or_else(|e| {
884 common_telemetry::error!(e; "Unable to build JSON2 vector");
886 Arc::new(NullVector::new(self.len()))
887 })
888 }
889
890 fn try_push_value_ref(&mut self, value: &ValueRef) -> Result<()> {
891 self.state.try_push_value_ref(value)
892 }
893
894 fn push_null(&mut self) {
895 self.state.push_null()
896 }
897
898 fn extend_slice_of(&mut self, _: &dyn Vector, _: usize, _: usize) -> Result<()> {
899 UnsupportedOperationSnafu {
900 op: "extend_slice_of",
901 vector_type: "JsonVector",
902 }
903 .fail()
904 }
905}
906
907#[cfg(test)]
908mod tests {
909 use std::sync::Arc;
910
911 use arrow_array::cast::AsArray;
912 use arrow_schema::Field;
913 use common_base::bytes::Bytes;
914 use serde_json::json;
915
916 use super::*;
917 use crate::data_type::ConcreteDataType;
918 use crate::extension::json::{Json2ExtensionType, JsonMetadata};
919 use crate::json::JsonTypeHint;
920 use crate::json::value::decode_json_variant;
921 use crate::types::StructField;
922 use crate::types::json_type::JsonObjectType;
923 use crate::value::{ListValue, StructValue, Value, ValueRef};
924 use crate::vectors::json::array::JsonArray;
925 use crate::vectors::json::variant::variant_to_json_values;
926
927 #[test]
928 fn test_json_vector_builder() -> Result<()> {
929 fn parse_json_value(json: &str) -> Value {
930 let value: serde_json::Value = serde_json::from_str(json).unwrap();
931 Value::Json(Box::new(value.into()))
932 }
933
934 fn jsonb_bytes(json: &str) -> Bytes {
935 Bytes::from(jsonb::parse_value(json.as_bytes()).unwrap().to_vec())
936 }
937
938 let mut builder = JsonVectorBuilder::new(JsonNativeType::Object(Default::default()), 3);
941 let first = parse_json_value(r#"{"id":1,"payload":{"name":"foo"}}"#);
942 let second = parse_json_value(r#"{"id":2,"extra":true,"payload":"raw"}"#);
943 builder.try_push_value_ref(&first.as_value_ref())?;
944 builder.push_null();
945 builder.try_push_value_ref(&second.as_value_ref())?;
946
947 let merged_type = JsonNativeType::Object(JsonObjectType::from([
948 ("extra".to_string(), JsonNativeType::Bool),
949 ("id".to_string(), JsonNativeType::i64()),
950 ("payload".to_string(), JsonNativeType::Variant),
951 ]));
952 assert_eq!(
953 builder.data_type(),
954 ConcreteDataType::json2(merged_type.clone())
955 );
956
957 let DataType::Struct(fields) = merged_type.as_arrow_type() else {
958 unreachable!()
959 };
960 let merged_struct_type = StructType::from(&fields);
961 let vector = builder.to_vector();
962 assert_eq!(vector.len(), 3);
963 assert_eq!(
964 vector.get(0),
965 Value::Struct(StructValue::new(
966 vec![
967 Value::Null,
968 Value::Int64(1),
969 Value::Binary(jsonb_bytes(r#"{"name":"foo"}"#)),
970 ],
971 merged_struct_type.clone(),
972 ))
973 );
974 assert_eq!(vector.get(1), Value::Null);
975 assert_eq!(
976 vector.get(2),
977 Value::Struct(StructValue::new(
978 vec![
979 Value::Boolean(true),
980 Value::Int64(2),
981 Value::Binary(jsonb_bytes(r#""raw""#)),
982 ],
983 merged_struct_type,
984 ))
985 );
986
987 let mut inferred_builder = JsonVectorBuilder::new(JsonNativeType::Null, 2);
990 let inferred_value = parse_json_value(r#"{"id":3}"#);
991 inferred_builder.push_null();
992 inferred_builder.try_push_value_ref(&inferred_value.as_value_ref())?;
993
994 let inferred_type = JsonNativeType::Object(JsonObjectType::from([(
995 "id".to_string(),
996 JsonNativeType::i64(),
997 )]));
998 assert_eq!(
999 inferred_builder.data_type(),
1000 ConcreteDataType::json2(inferred_type.clone())
1001 );
1002
1003 let DataType::Struct(fields) = inferred_type.as_arrow_type() else {
1004 unreachable!()
1005 };
1006 let inferred_struct_type = StructType::from(&fields);
1007 let vector = inferred_builder.to_vector();
1008 assert_eq!(vector.get(0), Value::Null);
1009 assert_eq!(
1010 vector.get(1),
1011 Value::Struct(StructValue::new(
1012 vec![Value::Int64(3)],
1013 inferred_struct_type,
1014 ))
1015 );
1016
1017 let result = std::panic::catch_unwind(|| JsonVectorBuilder::new(JsonNativeType::Bool, 2));
1019 assert!(result.is_err());
1020
1021 let mut object_builder =
1023 JsonVectorBuilder::new(JsonNativeType::Object(Default::default()), 2);
1024 let object = parse_json_value(r#"{"k":1}"#);
1025 let boolean = parse_json_value("true");
1026 let err = object_builder
1027 .try_push_value_ref(&boolean.as_value_ref())
1028 .unwrap_err();
1029 assert!(err.to_string().contains("expected JSON object value"));
1030 object_builder.try_push_value_ref(&object.as_value_ref())?;
1031
1032 let mut invalid_builder =
1034 JsonVectorBuilder::new(JsonNativeType::Object(Default::default()), 1);
1035 let err = invalid_builder
1036 .try_push_value_ref(&ValueRef::Boolean(true))
1037 .unwrap_err();
1038 assert!(err.to_string().contains("expected JSON value"));
1039
1040 Ok(())
1041 }
1042
1043 #[test]
1044 fn test_zero_budget_builder_uses_explicit_only_schema_and_remainder() -> Result<()> {
1045 let settings = JsonSettings::try_new(
1046 vec![
1047 JsonTypeHint {
1048 path: vec!["kind".to_string()],
1049 data_type: ConcreteDataType::string_datatype(),
1050 nullable: true,
1051 default_constraint: None,
1052 inverted_index: false,
1053 },
1054 JsonTypeHint {
1055 path: vec!["commit".to_string(), "operation".to_string()],
1056 data_type: ConcreteDataType::string_datatype(),
1057 nullable: true,
1058 default_constraint: None,
1059 inverted_index: false,
1060 },
1061 JsonTypeHint {
1062 path: vec!["time_us".to_string()],
1063 data_type: ConcreteDataType::int64_datatype(),
1064 nullable: true,
1065 default_constraint: None,
1066 inverted_index: false,
1067 },
1068 ],
1069 Some(0),
1070 )?;
1071 let mut builder = JsonVectorBuilder::with_settings(&settings, 2);
1072 assert!(matches!(
1073 &builder.state,
1074 JsonVectorBuilderState::ExplicitOnly { .. }
1075 ));
1076 let values = [
1077 json!({
1078 "kind": "record",
1079 "commit": {"operation": "create", "collection": "post"},
1080 "extra": 1,
1081 "time_us": 1
1082 }),
1083 json!({"kind": "other", "dynamic": true, "time_us": 2}),
1084 ];
1085 for value in values.clone() {
1086 let value = settings.encode(value)?;
1087 builder.try_push_value_ref(&value.as_value_ref())?;
1088 }
1089 let array = builder.to_vector().to_arrow_array();
1090 assert_eq!(&json2_physical_data_type(&settings), array.data_type());
1091 assert_eq!(0, builder.len());
1092 let structs = array.as_struct();
1093 assert_eq!(
1094 vec![JSON2_REMAINDER_FIELD_NAME, "commit", "kind", "time_us"],
1095 structs
1096 .fields()
1097 .iter()
1098 .map(|x| x.name().as_str())
1099 .collect::<Vec<_>>()
1100 );
1101 assert_eq!(
1102 vec![
1103 Some(json!({"commit": {"collection": "post"}, "extra": 1})),
1104 Some(json!({"commit": {"operation": null}, "dynamic": true})),
1105 ],
1106 variant_to_json_values(structs.column_by_name(JSON2_REMAINDER_FIELD_NAME).unwrap())?
1107 );
1108
1109 let field = Field::new("data", array.data_type().clone(), true).with_extension_type(
1110 Json2ExtensionType::new(Arc::new(JsonMetadata::new(settings))),
1111 );
1112 let reconstructed = JsonArray::from(&array).project_to_v2(&field, &DataType::Binary)?;
1113 let reconstructed = reconstructed.as_binary::<i32>();
1114 assert_eq!(
1115 values[0],
1116 decode_json_variant(reconstructed.value(0)).unwrap()
1117 );
1118 assert_eq!(
1119 json!({
1120 "kind": "other",
1121 "commit": {"operation": null},
1122 "dynamic": true,
1123 "time_us": 2
1124 }),
1125 decode_json_variant(reconstructed.value(1)).unwrap()
1126 );
1127
1128 let settings = JsonSettings::try_new(vec![], Some(0))?;
1129 let mut builder = JsonVectorBuilder::with_settings(&settings, 3);
1130 for value in [json!({}), json!({"x": 1})] {
1131 let value = settings.encode(value)?;
1132 builder.try_push_value_ref(&value.as_value_ref())?;
1133 }
1134 builder.push_null();
1135 let array = builder.to_vector().to_arrow_array();
1136 let structs = array.as_struct();
1137 assert_eq!(1, structs.num_columns());
1138 assert_eq!(
1139 vec![Some(json!({})), Some(json!({"x": 1})), None],
1140 variant_to_json_values(structs.column(0))?
1141 );
1142
1143 Ok(())
1144 }
1145
1146 #[test]
1147 fn test_finite_budget_selects_dynamic_paths() -> Result<()> {
1148 let builder = JsonVectorBuilder::with_settings(&JsonSettings::default(), 0);
1149 assert!(matches!(
1150 builder.state,
1151 JsonVectorBuilderState::AutoExpanding {
1152 max_auto_expanded_paths: JSON2_DEFAULT_MAX_AUTO_EXPANDED_PATHS,
1153 ..
1154 }
1155 ));
1156
1157 let settings = JsonSettings::try_new(
1158 vec![JsonTypeHint {
1159 path: vec!["hint".to_string()],
1160 data_type: ConcreteDataType::string_datatype(),
1161 nullable: true,
1162 default_constraint: None,
1163 inverted_index: false,
1164 }],
1165 Some(2),
1166 )?;
1167 let values = [
1168 json!({
1169 "hint": "first",
1170 "conflict": 1,
1171 "popular": {"nested": 1},
1172 "tie_a": "a",
1173 "tie_b": true,
1174 "rare": 1
1175 }),
1176 json!({
1177 "hint": "second",
1178 "conflict": "string",
1179 "popular": {"nested": 2},
1180 "tie_a": "b",
1181 "tie_b": false
1182 }),
1183 json!({"hint": "third", "popular": "scalar"}),
1184 ];
1185 let mut builder = JsonVectorBuilder::with_settings(&settings, values.len());
1186 for value in values.clone() {
1187 let value = settings.encode(value)?;
1188 builder.try_push_value_ref(&value.as_value_ref())?;
1189 }
1190
1191 let array = builder.to_vector().to_arrow_array();
1192 let structs = array.as_struct();
1193 assert_eq!(
1194 vec![JSON2_REMAINDER_FIELD_NAME, "hint", "tie_a", "tie_b"],
1195 structs
1196 .fields()
1197 .iter()
1198 .map(|x| x.name().as_str())
1199 .collect::<Vec<_>>()
1200 );
1201 assert!(structs.column_by_name("popular").is_none());
1202 assert_eq!(
1203 vec![
1204 Some(json!({"conflict": 1, "popular": {"nested": 1}, "rare": 1})),
1205 Some(json!({"conflict": "string", "popular": {"nested": 2}})),
1206 Some(json!({"popular": "scalar"})),
1207 ],
1208 variant_to_json_values(structs.column_by_name(JSON2_REMAINDER_FIELD_NAME).unwrap())?
1209 );
1210
1211 let field = Field::new("data", array.data_type().clone(), true).with_extension_type(
1212 Json2ExtensionType::new(Arc::new(JsonMetadata::new(settings))),
1213 );
1214 let reconstructed = JsonArray::from(&array).project_to_v2(&field, &DataType::Binary)?;
1215 let reconstructed = reconstructed.as_binary::<i32>();
1216 assert_eq!(
1217 values[0],
1218 decode_json_variant(reconstructed.value(0)).unwrap()
1219 );
1220 assert_eq!(
1221 values[1],
1222 decode_json_variant(reconstructed.value(1)).unwrap()
1223 );
1224 assert_eq!(
1225 json!({
1226 "hint": "third",
1227 "popular": "scalar"
1228 }),
1229 decode_json_variant(reconstructed.value(2)).unwrap()
1230 );
1231
1232 Ok(())
1233 }
1234
1235 #[test]
1236 fn test_v2_builder_preserves_explicit_null_presence() -> Result<()> {
1237 let settings = JsonSettings::try_new(vec![], Some(1))?;
1238 let values = [json!({"value": 1}), json!({"value": null}), json!({})];
1239 let mut builder = JsonVectorBuilder::with_settings(&settings, values.len());
1240 for value in values.clone() {
1241 let value = settings.encode(value)?;
1242 builder.try_push_value_ref(&value.as_value_ref())?;
1243 }
1244 let array = builder.to_vector().to_arrow_array();
1245 let structs = array.as_struct();
1246 assert_eq!(
1247 vec![
1248 Some(json!({})),
1249 Some(json!({"value": null})),
1250 Some(json!({}))
1251 ],
1252 variant_to_json_values(structs.column_by_name(JSON2_REMAINDER_FIELD_NAME).unwrap())?
1253 );
1254 let field = Field::new("data", array.data_type().clone(), true).with_extension_type(
1255 Json2ExtensionType::new(Arc::new(JsonMetadata::new(settings))),
1256 );
1257 let reconstructed = JsonArray::from(&array).project_to_v2(&field, &DataType::Binary)?;
1258 let reconstructed = reconstructed.as_binary::<i32>();
1259
1260 assert_eq!(
1261 values[0],
1262 decode_json_variant(reconstructed.value(0)).unwrap()
1263 );
1264 assert_eq!(
1265 values[1],
1266 decode_json_variant(reconstructed.value(1)).unwrap()
1267 );
1268 assert_eq!(
1269 values[2],
1270 decode_json_variant(reconstructed.value(2)).unwrap()
1271 );
1272 Ok(())
1273 }
1274
1275 #[test]
1276 fn test_reconstruct_nested_remainder_only_value() -> Result<()> {
1277 let settings = JsonSettings::try_new(vec![], Some(1))?;
1278 let values = [
1279 json!({"a": {"hot": 1}}),
1280 json!({"a": {"hot": 2}}),
1281 json!({"a": {"cold": 3}}),
1282 ];
1283 let mut builder = JsonVectorBuilder::with_settings(&settings, values.len());
1284 for value in values.clone() {
1285 let value = settings.encode(value)?;
1286 builder.try_push_value_ref(&value.as_value_ref())?;
1287 }
1288
1289 let array = builder.to_vector().to_arrow_array();
1290 let field = Field::new("data", array.data_type().clone(), true).with_extension_type(
1291 Json2ExtensionType::new(Arc::new(JsonMetadata::new(settings))),
1292 );
1293 let reconstructed = JsonArray::from(&array).project_to_v2(&field, &DataType::Binary)?;
1294 let reconstructed = reconstructed.as_binary::<i32>();
1295 assert_eq!(
1296 vec![values[0].clone(), values[1].clone(), values[2].clone()],
1297 (0..reconstructed.len())
1298 .map(|i| decode_json_variant(reconstructed.value(i)).unwrap())
1299 .collect::<Vec<_>>()
1300 );
1301
1302 Ok(())
1303 }
1304
1305 #[test]
1306 fn test_dynamic_paths_require_the_same_leaf_type() -> Result<()> {
1307 let settings = JsonSettings::try_new(
1308 vec![JsonTypeHint {
1309 path: vec!["nested".to_string(), "hinted".to_string()],
1310 data_type: ConcreteDataType::string_datatype(),
1311 nullable: true,
1312 default_constraint: None,
1313 inverted_index: false,
1314 }],
1315 Some(8),
1316 )?;
1317 let values = [
1318 json!({
1319 "branch": {},
1320 "different": [1],
1321 "empty": {},
1322 "nested": {},
1323 "reverse": "scalar",
1324 "same": [1]
1325 }),
1326 json!({
1327 "branch": {"leaf": 1},
1328 "different": ["x"],
1329 "empty": {},
1330 "nested": {"hinted": "x", "leaf": 1},
1331 "same": [2]
1332 }),
1333 json!({
1334 "branch": {},
1335 "different": [2],
1336 "empty": {},
1337 "nested": {},
1338 "reverse": {"leaf": 1},
1339 "same": [3]
1340 }),
1341 ];
1342 let mut builder = JsonVectorBuilder::with_settings(&settings, values.len());
1343 for value in values {
1344 let value = settings.encode(value)?;
1345 builder.try_push_value_ref(&value.as_value_ref())?;
1346 }
1347
1348 let JsonNativeType::Object(fields) = builder.state.native_type() else {
1349 unreachable!();
1350 };
1351 assert!(!fields.contains_key("different"));
1352 assert!(!fields.contains_key("empty"));
1353 assert!(!fields.contains_key("reverse"));
1354 assert!(matches!(fields.get("same"), Some(JsonNativeType::Array(_))));
1355 assert!(matches!(
1356 fields.get("branch"),
1357 Some(JsonNativeType::Object(fields)) if fields.contains_key("leaf")
1358 ));
1359 assert!(matches!(
1360 fields.get("nested"),
1361 Some(JsonNativeType::Object(fields))
1362 if fields.contains_key("hinted") && fields.contains_key("leaf")
1363 ));
1364
1365 Ok(())
1366 }
1367
1368 #[test]
1369 fn test_json_variant_into_struct_value() -> Result<()> {
1370 let struct_type = StructType::new(Arc::new(vec![StructField::new(
1371 "value".to_string(),
1372 ConcreteDataType::string_datatype(),
1373 true,
1374 )]));
1375 assert_eq!(
1376 json_variant_into_value(
1377 JsonVariant::Object(Default::default()),
1378 &ConcreteDataType::struct_datatype(struct_type.clone()),
1379 false,
1380 )?,
1381 Value::Null
1382 );
1383 assert_eq!(
1384 json_variant_into_value(
1385 JsonVariant::Object(Default::default()),
1386 &ConcreteDataType::struct_datatype(struct_type.clone()),
1387 true,
1388 )?,
1389 Value::Struct(StructValue::new(vec![Value::Null], struct_type))
1390 );
1391
1392 let item_type =
1393 ConcreteDataType::struct_datatype(StructType::new(Arc::new(vec![StructField::new(
1394 "id".to_string(),
1395 ConcreteDataType::int64_datatype(),
1396 true,
1397 )])));
1398 let struct_type = StructType::new(Arc::new(vec![
1399 StructField::new(
1400 "items".to_string(),
1401 ConcreteDataType::list_datatype(Arc::new(item_type.clone())),
1402 true,
1403 ),
1404 StructField::new(
1405 "meta".to_string(),
1406 ConcreteDataType::struct_datatype(StructType::new(Arc::new(vec![
1407 StructField::new(
1408 "name".to_string(),
1409 ConcreteDataType::string_datatype(),
1410 true,
1411 ),
1412 ]))),
1413 true,
1414 ),
1415 ]));
1416 let variant = JsonObjectValue::from([
1417 (
1418 "items".to_string(),
1419 JsonVariant::Array(vec![
1420 JsonVariant::from([("id", JsonVariant::from(1i64))]),
1421 JsonVariant::from([("id", JsonVariant::from(2i64))]),
1422 ]),
1423 ),
1424 (
1425 "meta".to_string(),
1426 JsonVariant::from([("name", JsonVariant::from("foo"))]),
1427 ),
1428 ]);
1429 let value = Value::Struct(json_variant_into_struct_value(
1430 variant,
1431 struct_type.clone(),
1432 true,
1433 )?);
1434
1435 assert_eq!(
1436 value,
1437 Value::Struct(StructValue::new(
1438 vec![
1439 Value::List(ListValue::new(
1440 vec![
1441 Value::Struct(StructValue::new(
1442 vec![Value::Int64(1)],
1443 StructType::new(Arc::new(vec![StructField::new(
1444 "id".to_string(),
1445 ConcreteDataType::int64_datatype(),
1446 true,
1447 )]))
1448 )),
1449 Value::Struct(StructValue::new(
1450 vec![Value::Int64(2)],
1451 StructType::new(Arc::new(vec![StructField::new(
1452 "id".to_string(),
1453 ConcreteDataType::int64_datatype(),
1454 true,
1455 )]))
1456 )),
1457 ],
1458 Arc::new(item_type),
1459 )),
1460 Value::Struct(StructValue::new(
1461 vec![Value::String("foo".into())],
1462 StructType::new(Arc::new(vec![StructField::new(
1463 "name".to_string(),
1464 ConcreteDataType::string_datatype(),
1465 true,
1466 )])),
1467 )),
1468 ],
1469 struct_type,
1470 ))
1471 );
1472 Ok(())
1473 }
1474}