1use std::collections::HashSet;
23use std::sync::Arc;
24
25use common_base::bytes::StringBytes;
26use ordered_float::OrderedFloat;
27use serde::{Deserialize, Serialize};
28use serde_json::{Map, Value as Json};
29use snafu::{ResultExt, ensure};
30
31use crate::data_type::{ConcreteDataType, DataType};
32use crate::error::{self, Error};
33use crate::types::{ListType, StructField, StructType};
34use crate::value::{ListValue, StructValue, Value};
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
50pub enum JsonStructureSettings {
51 Structured(Option<StructType>),
53 UnstructuredRaw,
54 PartialUnstructuredByKey {
55 fields: Option<StructType>,
56 unstructured_keys: HashSet<String>,
57 },
58}
59
60#[derive(Clone, Debug)]
62pub struct JsonContext<'a> {
63 pub key_path: String,
65 pub settings: &'a JsonStructureSettings,
67}
68
69impl JsonStructureSettings {
70 pub const RAW_FIELD: &'static str = "_raw";
71
72 pub fn decode(&self, value: Value) -> Result<Json, Error> {
74 let context = JsonContext {
75 key_path: String::new(),
76 settings: self,
77 };
78 decode_value_with_context(value, &context)
79 }
80
81 pub fn decode_struct(&self, struct_value: StructValue) -> Result<StructValue, Error> {
85 let context = JsonContext {
86 key_path: String::new(),
87 settings: self,
88 };
89 decode_struct_with_settings(struct_value, &context)
90 }
91
92 pub fn encode(&self, json: Json) -> Result<Value, Error> {
94 let context = JsonContext {
95 key_path: String::new(),
96 settings: self,
97 };
98 encode_json_with_context(json, None, &context).map(|v| Value::Json(Box::new(v)))
99 }
100
101 pub fn encode_with_type(
103 &self,
104 json: Json,
105 data_type: Option<&ConcreteDataType>,
106 ) -> Result<Value, Error> {
107 let context = JsonContext {
108 key_path: String::new(),
109 settings: self,
110 };
111 encode_json_with_context(json, data_type, &context).map(|v| Value::Json(Box::new(v)))
112 }
113}
114
115impl Default for JsonStructureSettings {
116 fn default() -> Self {
117 Self::Structured(None)
118 }
119}
120
121impl<'a> JsonContext<'a> {
122 pub fn with_key(&self, key: &str) -> JsonContext<'a> {
124 let new_key_path = if self.key_path.is_empty() {
125 key.to_string()
126 } else {
127 format!("{}.{}", self.key_path, key)
128 };
129 JsonContext {
130 key_path: new_key_path,
131 settings: self.settings,
132 }
133 }
134
135 pub fn is_unstructured_key(&self) -> bool {
137 match &self.settings {
138 JsonStructureSettings::PartialUnstructuredByKey {
139 unstructured_keys, ..
140 } => unstructured_keys.contains(&self.key_path),
141 _ => false,
142 }
143 }
144}
145
146pub fn encode_json_with_context<'a>(
148 json: Json,
149 data_type: Option<&ConcreteDataType>,
150 context: &JsonContext<'a>,
151) -> Result<Value, Error> {
152 if matches!(context.settings, JsonStructureSettings::UnstructuredRaw) {
154 let json_string = json.to_string();
155 let struct_value = StructValue::try_new(
156 vec![Value::String(json_string.into())],
157 StructType::new(Arc::new(vec![StructField::new(
158 JsonStructureSettings::RAW_FIELD.to_string(),
159 ConcreteDataType::string_datatype(),
160 true,
161 )])),
162 )?;
163 return Ok(Value::Struct(struct_value));
164 }
165
166 if context.is_unstructured_key() {
168 return Ok(Value::String(json.to_string().into()));
169 }
170
171 match json {
172 Json::Object(json_object) => {
173 ensure!(
174 matches!(data_type, Some(ConcreteDataType::Struct(_)) | None),
175 error::InvalidJsonSnafu {
176 value: "JSON object can only be encoded to Struct type".to_string(),
177 }
178 );
179
180 let data_type = data_type.and_then(|x| x.as_struct());
181 let struct_value = encode_json_object_with_context(json_object, data_type, context)?;
182 Ok(Value::Struct(struct_value))
183 }
184 Json::Array(json_array) => {
185 let item_type = if let Some(ConcreteDataType::List(list_type)) = data_type {
186 Some(list_type.item_type())
187 } else {
188 None
189 };
190 let list_value = encode_json_array_with_context(json_array, item_type, context)?;
191 Ok(Value::List(list_value))
192 }
193 _ => {
194 if let Some(expected_type) = data_type {
196 let (value, actual_type) =
197 encode_json_value_with_context(json, Some(expected_type), context)?;
198 if &actual_type == expected_type {
199 Ok(value)
200 } else {
201 Err(error::InvalidJsonSnafu {
202 value: format!(
203 "JSON value type {} does not match expected type {}",
204 actual_type.name(),
205 expected_type.name()
206 ),
207 }
208 .build())
209 }
210 } else {
211 let (value, _) = encode_json_value_with_context(json, None, context)?;
212 Ok(value)
213 }
214 }
215 }
216}
217
218fn encode_json_object_with_context<'a>(
219 mut json_object: Map<String, Json>,
220 fields: Option<&StructType>,
221 context: &JsonContext<'a>,
222) -> Result<StructValue, Error> {
223 let total_json_keys = json_object.len();
224 let mut items = Vec::with_capacity(total_json_keys);
225 let mut struct_fields = Vec::with_capacity(total_json_keys);
226 if let Some(fields) = fields {
228 for field in fields.fields().iter() {
229 let field_name = field.name();
230
231 if let Some(value) = json_object.remove(field_name) {
232 let field_context = context.with_key(field_name);
233 let (value, data_type) =
234 encode_json_value_with_context(value, Some(field.data_type()), &field_context)?;
235 items.push(value);
236 struct_fields.push(StructField::new(
237 field_name.to_string(),
238 data_type,
239 true, ));
241 } else {
242 items.push(Value::Null);
244 struct_fields.push(field.clone());
245 }
246 }
247 }
248
249 for (key, value) in json_object {
251 let field_context = context.with_key(&key);
252
253 let (value, data_type) = encode_json_value_with_context(value, None, &field_context)?;
254 items.push(value);
255
256 struct_fields.push(StructField::new(
257 key.clone(),
258 data_type,
259 true, ));
261 }
262
263 let struct_type = StructType::new(Arc::new(struct_fields));
264 StructValue::try_new(items, struct_type)
265}
266
267fn encode_json_array_with_context<'a>(
268 json_array: Vec<Json>,
269 item_type: Option<&ConcreteDataType>,
270 context: &JsonContext<'a>,
271) -> Result<ListValue, Error> {
272 let json_array_len = json_array.len();
273 let mut items = Vec::with_capacity(json_array_len);
274 let mut element_type = None;
275
276 for (index, value) in json_array.into_iter().enumerate() {
277 let array_context = context.with_key(&index.to_string());
278 let (item_value, item_type) =
279 encode_json_value_with_context(value, item_type, &array_context)?;
280 items.push(item_value);
281
282 if let Some(current_type) = &element_type {
284 if *current_type == ConcreteDataType::null_datatype()
287 && item_type != ConcreteDataType::null_datatype()
288 {
289 element_type = Some(item_type);
290 }
291 } else {
292 element_type = Some(item_type);
293 }
294 }
295
296 let element_type = if let Some(item_type) = item_type {
298 item_type.clone()
299 } else {
300 element_type.unwrap_or_else(ConcreteDataType::string_datatype)
301 };
302
303 Ok(ListValue::new(items, Arc::new(element_type)))
304}
305
306fn encode_json_value_with_context<'a>(
308 json: Json,
309 expected_type: Option<&ConcreteDataType>,
310 context: &JsonContext<'a>,
311) -> Result<(Value, ConcreteDataType), Error> {
312 if context.is_unstructured_key() {
314 return Ok((
315 Value::String(json.to_string().into()),
316 ConcreteDataType::string_datatype(),
317 ));
318 }
319
320 match json {
321 Json::Null => Ok((Value::Null, ConcreteDataType::null_datatype())),
322 Json::Bool(b) => Ok((Value::Boolean(b), ConcreteDataType::boolean_datatype())),
323 Json::Number(n) => {
324 if let Some(i) = n.as_i64() {
325 if let Some(expected) = expected_type
327 && let Ok(value) = try_convert_to_expected_type(i, expected)
328 {
329 return Ok((value, expected.clone()));
330 }
331 Ok((Value::Int64(i), ConcreteDataType::int64_datatype()))
332 } else if let Some(u) = n.as_u64() {
333 if let Some(expected) = expected_type
335 && let Ok(value) = try_convert_to_expected_type(u, expected)
336 {
337 return Ok((value, expected.clone()));
338 }
339 if u <= i64::MAX as u64 {
340 Ok((Value::Int64(u as i64), ConcreteDataType::int64_datatype()))
341 } else {
342 Ok((Value::UInt64(u), ConcreteDataType::uint64_datatype()))
343 }
344 } else if let Some(f) = n.as_f64() {
345 if let Some(expected) = expected_type
347 && let Ok(value) = try_convert_to_expected_type(f, expected)
348 {
349 return Ok((value, expected.clone()));
350 }
351
352 Ok((
354 Value::Float64(OrderedFloat(f)),
355 ConcreteDataType::float64_datatype(),
356 ))
357 } else {
358 Ok((
360 Value::String(StringBytes::from(n.to_string())),
361 ConcreteDataType::string_datatype(),
362 ))
363 }
364 }
365 Json::String(s) => {
366 if let Some(expected) = expected_type
367 && let Ok(value) = try_convert_to_expected_type(s.as_str(), expected)
368 {
369 return Ok((value, expected.clone()));
370 }
371 Ok((
372 Value::String(StringBytes::from(s.clone())),
373 ConcreteDataType::string_datatype(),
374 ))
375 }
376 Json::Array(arr) => {
377 let list_value = encode_json_array_with_context(arr, expected_type, context)?;
378 let datatype = ConcreteDataType::List(ListType::new(list_value.datatype()));
379 Ok((Value::List(list_value), datatype))
380 }
381 Json::Object(obj) => {
382 let struct_value = encode_json_object_with_context(obj, None, context)?;
383 let data_type = ConcreteDataType::Struct(struct_value.struct_type().clone());
384 Ok((Value::Struct(struct_value), data_type))
385 }
386 }
387}
388
389pub fn decode_value_with_context<'a>(
391 value: Value,
392 context: &JsonContext<'a>,
393) -> Result<Json, Error> {
394 if matches!(context.settings, JsonStructureSettings::UnstructuredRaw) {
396 return decode_unstructured_value(value);
397 }
398
399 if context.is_unstructured_key() {
401 return decode_unstructured_value(value);
402 }
403
404 match value {
405 Value::Json(inner) => decode_value_with_context(*inner, context),
406 Value::Struct(struct_value) => decode_struct_with_context(struct_value, context),
407 Value::List(list_value) => decode_list_with_context(list_value, context),
408 _ => decode_primitive_value(value),
409 }
410}
411
412fn decode_struct_with_context<'a>(
414 struct_value: StructValue,
415 context: &JsonContext<'a>,
416) -> Result<Json, Error> {
417 let mut json_object = Map::with_capacity(struct_value.len());
418
419 let (items, fields) = struct_value.into_parts();
420
421 for (field, field_value) in fields.fields().iter().zip(items.into_iter()) {
422 let field_context = context.with_key(field.name());
423 let json_value = decode_value_with_context(field_value, &field_context)?;
424 json_object.insert(field.name().to_string(), json_value);
425 }
426
427 Ok(Json::Object(json_object))
428}
429
430fn decode_list_with_context<'a>(
432 list_value: ListValue,
433 context: &JsonContext<'a>,
434) -> Result<Json, Error> {
435 let mut json_array = Vec::with_capacity(list_value.len());
436
437 let data_items = list_value.take_items();
438
439 for (index, item) in data_items.into_iter().enumerate() {
440 let array_context = context.with_key(&index.to_string());
441 let json_value = decode_value_with_context(item, &array_context)?;
442 json_array.push(json_value);
443 }
444
445 Ok(Json::Array(json_array))
446}
447
448fn decode_unstructured_value(value: Value) -> Result<Json, Error> {
450 match value {
451 Value::Struct(struct_value) => {
453 if struct_value.struct_type().fields().len() == 1 {
454 let field = &struct_value.struct_type().fields()[0];
455 if field.name() == JsonStructureSettings::RAW_FIELD
456 && let Some(Value::String(s)) = struct_value.items().first()
457 {
458 let json_str = s.as_utf8();
459 return serde_json::from_str(json_str).with_context(|_| {
460 error::DeserializeSnafu {
461 json: json_str.to_string(),
462 }
463 });
464 }
465 }
466 Err(error::InvalidJsonSnafu {
468 value: "Unstructured value must be stored as struct with single _raw field"
469 .to_string(),
470 }
471 .build())
472 }
473 Value::String(s) => {
475 let json_str = s.as_utf8();
476 serde_json::from_str(json_str).with_context(|_| error::DeserializeSnafu {
477 json: json_str.to_string(),
478 })
479 }
480 _ => Err(error::InvalidJsonSnafu {
481 value: "Unstructured value must be stored as string or struct with _raw field"
482 .to_string(),
483 }
484 .build()),
485 }
486}
487
488fn decode_primitive_value(value: Value) -> Result<Json, Error> {
490 match value {
491 Value::Null => Ok(Json::Null),
492 Value::Boolean(b) => Ok(Json::Bool(b)),
493 Value::UInt8(v) => Ok(Json::from(v)),
494 Value::UInt16(v) => Ok(Json::from(v)),
495 Value::UInt32(v) => Ok(Json::from(v)),
496 Value::UInt64(v) => Ok(Json::from(v)),
497 Value::Int8(v) => Ok(Json::from(v)),
498 Value::Int16(v) => Ok(Json::from(v)),
499 Value::Int32(v) => Ok(Json::from(v)),
500 Value::Int64(v) => Ok(Json::from(v)),
501 Value::Float32(v) => Ok(Json::from(v.0)),
502 Value::Float64(v) => Ok(Json::from(v.0)),
503 Value::String(s) => Ok(Json::String(s.as_utf8().to_string())),
504 Value::Binary(b) => serde_json::to_value(b.as_ref()).context(error::SerializeSnafu),
505 Value::Date(v) => Ok(Json::from(v.val())),
506 Value::Timestamp(v) => serde_json::to_value(v.value()).context(error::SerializeSnafu),
507 Value::Time(v) => serde_json::to_value(v.value()).context(error::SerializeSnafu),
508 Value::IntervalYearMonth(v) => {
509 serde_json::to_value(v.to_i32()).context(error::SerializeSnafu)
510 }
511 Value::IntervalDayTime(v) => {
512 serde_json::to_value(v.to_i64()).context(error::SerializeSnafu)
513 }
514 Value::IntervalMonthDayNano(v) => {
515 serde_json::to_value(v.to_i128()).context(error::SerializeSnafu)
516 }
517 Value::Duration(v) => serde_json::to_value(v.value()).context(error::SerializeSnafu),
518 Value::Decimal128(v) => serde_json::to_value(v.to_string()).context(error::SerializeSnafu),
519 Value::Struct(_) | Value::List(_) | Value::Json(_) => {
520 Err(error::InvalidJsonSnafu {
522 value: "Structured values should be handled by context-aware decoding".to_string(),
523 }
524 .build())
525 }
526 }
527}
528
529fn decode_struct_with_settings<'a>(
531 struct_value: StructValue,
532 context: &JsonContext<'a>,
533) -> Result<StructValue, Error> {
534 if matches!(context.settings, JsonStructureSettings::Structured(_)) {
536 return Ok(struct_value);
537 }
538
539 if let JsonStructureSettings::PartialUnstructuredByKey {
541 unstructured_keys, ..
542 } = context.settings
543 && unstructured_keys.is_empty()
544 {
545 return Ok(struct_value.clone());
546 }
547
548 if matches!(context.settings, JsonStructureSettings::UnstructuredRaw) {
550 return decode_unstructured_raw_struct(struct_value);
552 }
553
554 let mut items = Vec::with_capacity(struct_value.len());
555 let mut struct_fields = Vec::with_capacity(struct_value.len());
556
557 let (struct_data, fields) = struct_value.into_parts();
559 for (field, value) in fields.fields().iter().zip(struct_data.into_iter()) {
560 let field_context = context.with_key(field.name());
561
562 if field_context.is_unstructured_key() {
564 let json_value = decode_unstructured_value(value)?;
566
567 let structured_context = JsonContext {
569 key_path: field_context.key_path.clone(),
570 settings: &JsonStructureSettings::Structured(None),
571 };
572 let (decoded_value, data_type) = encode_json_value_with_context(
573 json_value,
574 None, &structured_context,
576 )?;
577
578 items.push(decoded_value);
579 struct_fields.push(StructField::new(
580 field.name().to_string(),
581 data_type,
582 true, ));
584 } else {
585 let decoded_value = match value {
587 Value::Struct(nested_struct) => {
588 let nested_context = context.with_key(field.name());
589 Value::Struct(decode_struct_with_settings(nested_struct, &nested_context)?)
590 }
591 Value::List(list_value) => {
592 let list_context = context.with_key(field.name());
593 Value::List(decode_list_with_settings(list_value, &list_context)?)
594 }
595 _ => value.clone(),
596 };
597
598 items.push(decoded_value);
599 struct_fields.push(field.clone());
600 }
601 }
602
603 let struct_type = StructType::new(Arc::new(struct_fields));
604 StructValue::try_new(items, struct_type)
605}
606
607fn decode_list_with_settings<'a>(
609 list_value: ListValue,
610 context: &JsonContext<'a>,
611) -> Result<ListValue, Error> {
612 let mut items = Vec::with_capacity(list_value.len());
613
614 let (data_items, datatype) = list_value.into_parts();
615
616 for (index, item) in data_items.into_iter().enumerate() {
617 let item_context = context.with_key(&index.to_string());
618
619 let decoded_item = match item {
620 Value::Struct(nested_struct) => {
621 Value::Struct(decode_struct_with_settings(nested_struct, &item_context)?)
622 }
623 Value::List(nested_list) => {
624 Value::List(decode_list_with_settings(nested_list, &item_context)?)
625 }
626 _ => item.clone(),
627 };
628
629 items.push(decoded_item);
630 }
631
632 Ok(ListValue::new(items, datatype))
633}
634
635fn decode_unstructured_raw_struct(struct_value: StructValue) -> Result<StructValue, Error> {
637 if struct_value.struct_type().fields().len() == 1 {
639 let field = &struct_value.struct_type().fields()[0];
640 if field.name() == JsonStructureSettings::RAW_FIELD
641 && let Some(Value::String(s)) = struct_value.items().first()
642 {
643 let json_str = s.as_utf8();
644 let json_value: Json =
645 serde_json::from_str(json_str).with_context(|_| error::DeserializeSnafu {
646 json: json_str.to_string(),
647 })?;
648
649 let context = JsonContext {
651 key_path: String::new(),
652 settings: &JsonStructureSettings::Structured(None),
653 };
654 let (decoded_value, data_type) =
655 encode_json_value_with_context(json_value, None, &context)?;
656
657 if let Value::Struct(decoded_struct) = decoded_value {
658 return Ok(decoded_struct);
659 } else {
660 let struct_type = StructType::new(Arc::new(vec![StructField::new(
662 "value".to_string(),
663 data_type,
664 true,
665 )]));
666 return StructValue::try_new(vec![decoded_value], struct_type);
667 }
668 }
669 }
670
671 Err(error::InvalidJsonSnafu {
673 value: "UnstructuredRaw value must be stored as struct with single _raw field".to_string(),
674 }
675 .build())
676}
677
678fn try_convert_to_expected_type<T>(
680 value: T,
681 expected_type: &ConcreteDataType,
682) -> Result<Value, Error>
683where
684 T: Into<Value>,
685{
686 let value = value.into();
687 expected_type.try_cast(value.clone()).ok_or_else(|| {
688 error::CastTypeSnafu {
689 msg: format!(
690 "Cannot cast from {} to {}",
691 value.data_type().name(),
692 expected_type.name()
693 ),
694 }
695 .build()
696 })
697}
698
699#[cfg(test)]
700mod tests {
701
702 use serde_json::json;
703
704 use super::*;
705 use crate::types::ListType;
706
707 #[test]
708 fn test_encode_json_null() {
709 let json = Json::Null;
710 let settings = JsonStructureSettings::Structured(None);
711 let result = settings
712 .encode_with_type(json, None)
713 .unwrap()
714 .into_json_inner()
715 .unwrap();
716 assert_eq!(result, Value::Null);
717 }
718
719 #[test]
720 fn test_encode_json_boolean() {
721 let json = Json::Bool(true);
722 let settings = JsonStructureSettings::Structured(None);
723 let result = settings
724 .encode_with_type(json, None)
725 .unwrap()
726 .into_json_inner()
727 .unwrap();
728 assert_eq!(result, Value::Boolean(true));
729 }
730
731 #[test]
732 fn test_encode_json_number_integer() {
733 let json = Json::from(42);
734 let settings = JsonStructureSettings::Structured(None);
735 let result = settings
736 .encode_with_type(json, None)
737 .unwrap()
738 .into_json_inner()
739 .unwrap();
740 assert_eq!(result, Value::Int64(42));
741 }
742
743 #[test]
744 fn test_encode_json_number_float() {
745 let json = Json::from(3.15);
746 let settings = JsonStructureSettings::Structured(None);
747 let result = settings
748 .encode_with_type(json, None)
749 .unwrap()
750 .into_json_inner()
751 .unwrap();
752 match result {
753 Value::Float64(f) => assert_eq!(f.0, 3.15),
754 _ => panic!("Expected Float64"),
755 }
756 }
757
758 #[test]
759 fn test_encode_json_string() {
760 let json = Json::String("hello".to_string());
761 let settings = JsonStructureSettings::Structured(None);
762 let result = settings
763 .encode_with_type(json, None)
764 .unwrap()
765 .into_json_inner()
766 .unwrap();
767 assert_eq!(result, Value::String("hello".into()));
768 }
769
770 #[test]
771 fn test_encode_json_array() {
772 let json = json!([1, 2, 3]);
773 let settings = JsonStructureSettings::Structured(None);
774 let result = settings
775 .encode_with_type(json, None)
776 .unwrap()
777 .into_json_inner()
778 .unwrap();
779
780 if let Value::List(list_value) = result {
781 assert_eq!(list_value.items().len(), 3);
782 assert_eq!(list_value.items()[0], Value::Int64(1));
783 assert_eq!(list_value.items()[1], Value::Int64(2));
784 assert_eq!(list_value.items()[2], Value::Int64(3));
785 } else {
786 panic!("Expected List value");
787 }
788 }
789
790 #[test]
791 fn test_encode_json_object() {
792 let json = json!({
793 "name": "John",
794 "age": 30,
795 "active": true
796 });
797
798 let settings = JsonStructureSettings::Structured(None);
799 let result = settings
800 .encode_with_type(json, None)
801 .unwrap()
802 .into_json_inner()
803 .unwrap();
804 let Value::Struct(result) = result else {
805 panic!("Expected Struct value");
806 };
807 assert_eq!(result.items().len(), 3);
808
809 let items = result.items();
810 let struct_type = result.struct_type();
811
812 let fields = struct_type.fields();
814 let field_names: Vec<&str> = fields.iter().map(|f| f.name()).collect();
815 assert!(field_names.contains(&"name"));
816 assert!(field_names.contains(&"age"));
817 assert!(field_names.contains(&"active"));
818
819 for (i, field) in struct_type.fields().iter().enumerate() {
821 match field.name() {
822 "name" => {
823 assert_eq!(items[i], Value::String("John".into()));
824 assert_eq!(field.data_type(), &ConcreteDataType::string_datatype());
825 }
826 "age" => {
827 assert_eq!(items[i], Value::Int64(30));
828 assert_eq!(field.data_type(), &ConcreteDataType::int64_datatype());
829 }
830 "active" => {
831 assert_eq!(items[i], Value::Boolean(true));
832 assert_eq!(field.data_type(), &ConcreteDataType::boolean_datatype());
833 }
834 _ => panic!("Unexpected field: {}", field.name()),
835 }
836 }
837 }
838
839 #[test]
840 fn test_encode_json_nested_object() {
841 let json = json!({
842 "person": {
843 "name": "Alice",
844 "age": 25
845 },
846 "scores": [95, 87, 92]
847 });
848
849 let settings = JsonStructureSettings::Structured(None);
850 let result = settings
851 .encode_with_type(json, None)
852 .unwrap()
853 .into_json_inner()
854 .unwrap();
855 let Value::Struct(result) = result else {
856 panic!("Expected Struct value");
857 };
858 assert_eq!(result.items().len(), 2);
859
860 let items = result.items();
861 let struct_type = result.struct_type();
862
863 let person_index = struct_type
865 .fields()
866 .iter()
867 .position(|f| f.name() == "person")
868 .unwrap();
869 if let Value::Struct(person_struct) = &items[person_index] {
870 assert_eq!(person_struct.items().len(), 2);
871 let fields = person_struct.struct_type().fields();
872 let person_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
873 assert!(person_fields.contains(&"name"));
874 assert!(person_fields.contains(&"age"));
875 } else {
876 panic!("Expected Struct value for person field");
877 }
878
879 let scores_index = struct_type
881 .fields()
882 .iter()
883 .position(|f| f.name() == "scores")
884 .unwrap();
885 if let Value::List(scores_list) = &items[scores_index] {
886 assert_eq!(scores_list.items().len(), 3);
887 assert_eq!(scores_list.items()[0], Value::Int64(95));
888 assert_eq!(scores_list.items()[1], Value::Int64(87));
889 assert_eq!(scores_list.items()[2], Value::Int64(92));
890 } else {
891 panic!("Expected List value for scores field");
892 }
893 }
894
895 #[test]
896 fn test_encode_json_with_expected_type() {
897 let json = Json::from(42);
899 let settings = JsonStructureSettings::Structured(None);
900 let result = settings
901 .encode_with_type(json.clone(), Some(&ConcreteDataType::int8_datatype()))
902 .unwrap()
903 .into_json_inner()
904 .unwrap();
905 assert_eq!(result, Value::Int8(42));
906
907 let result = settings
909 .encode_with_type(json, Some(&ConcreteDataType::string_datatype()))
910 .unwrap()
911 .into_json_inner()
912 .unwrap();
913 assert_eq!(result, Value::String("42".into()));
914 }
915
916 #[test]
917 fn test_encode_json_array_mixed_types() {
918 let json = json!([1, "hello", true, 3.15]);
919 let settings = JsonStructureSettings::Structured(None);
920 let result = settings
921 .encode_with_type(json, None)
922 .unwrap()
923 .into_json_inner()
924 .unwrap();
925
926 if let Value::List(list_value) = result {
927 assert_eq!(list_value.items().len(), 4);
928 assert_eq!(
931 list_value.datatype(),
932 Arc::new(ConcreteDataType::int64_datatype())
933 );
934 } else {
935 panic!("Expected List value");
936 }
937 }
938
939 #[test]
940 fn test_encode_json_empty_array() {
941 let json = json!([]);
942 let settings = JsonStructureSettings::Structured(None);
943 let result = settings
944 .encode_with_type(json, None)
945 .unwrap()
946 .into_json_inner()
947 .unwrap();
948
949 if let Value::List(list_value) = result {
950 assert_eq!(list_value.items().len(), 0);
951 assert_eq!(
953 list_value.datatype(),
954 Arc::new(ConcreteDataType::string_datatype())
955 );
956 } else {
957 panic!("Expected List value");
958 }
959 }
960
961 #[test]
962 fn test_encode_json_structured() {
963 let json = json!({
964 "name": "Bob",
965 "age": 35
966 });
967
968 let settings = JsonStructureSettings::Structured(None);
969 let result = settings.encode(json).unwrap().into_json_inner().unwrap();
970
971 if let Value::Struct(struct_value) = result {
972 assert_eq!(struct_value.items().len(), 2);
973 let fields = struct_value.struct_type().fields();
974 let field_names: Vec<&str> = fields.iter().map(|f| f.name()).collect();
975 assert!(field_names.contains(&"name"));
976 assert!(field_names.contains(&"age"));
977 } else {
978 panic!("Expected Struct value");
979 }
980 }
981
982 #[test]
983 fn test_encode_json_structured_with_fields() {
984 let json = json!({
985 "name": "Carol",
986 "age": 28
987 });
988
989 let fields = vec![
991 StructField::new(
992 "name".to_string(),
993 ConcreteDataType::string_datatype(),
994 true,
995 ),
996 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
997 ];
998 let struct_type = StructType::new(Arc::new(fields));
999 let concrete_type = ConcreteDataType::Struct(struct_type);
1000
1001 let settings = JsonStructureSettings::Structured(None);
1002 let result = settings
1003 .encode_with_type(json, Some(&concrete_type))
1004 .unwrap()
1005 .into_json_inner()
1006 .unwrap();
1007
1008 if let Value::Struct(struct_value) = result {
1009 assert_eq!(struct_value.items().len(), 2);
1010 let struct_fields = struct_value.struct_type().fields();
1011 assert_eq!(struct_fields[0].name(), "name");
1012 assert_eq!(
1013 struct_fields[0].data_type(),
1014 &ConcreteDataType::string_datatype()
1015 );
1016 assert_eq!(struct_fields[1].name(), "age");
1017 assert_eq!(
1018 struct_fields[1].data_type(),
1019 &ConcreteDataType::int64_datatype()
1020 );
1021 } else {
1022 panic!("Expected Struct value");
1023 }
1024 }
1025
1026 #[test]
1027 fn test_encode_json_object_field_order_preservation() {
1028 let json = json!({
1029 "z_field": "last",
1030 "a_field": "first",
1031 "m_field": "middle"
1032 });
1033
1034 let fields = vec![
1036 StructField::new(
1037 "a_field".to_string(),
1038 ConcreteDataType::string_datatype(),
1039 true,
1040 ),
1041 StructField::new(
1042 "m_field".to_string(),
1043 ConcreteDataType::string_datatype(),
1044 true,
1045 ),
1046 StructField::new(
1047 "z_field".to_string(),
1048 ConcreteDataType::string_datatype(),
1049 true,
1050 ),
1051 ];
1052 let struct_type = StructType::new(Arc::new(fields));
1053
1054 let result = encode_json_object_with_context(
1055 json.as_object().unwrap().clone(),
1056 Some(&struct_type),
1057 &JsonContext {
1058 key_path: String::new(),
1059 settings: &JsonStructureSettings::Structured(None),
1060 },
1061 )
1062 .unwrap();
1063
1064 let struct_fields = result.struct_type().fields();
1066 assert_eq!(struct_fields[0].name(), "a_field");
1067 assert_eq!(struct_fields[1].name(), "m_field");
1068 assert_eq!(struct_fields[2].name(), "z_field");
1069
1070 let items = result.items();
1072 assert_eq!(items[0], Value::String("first".into()));
1073 assert_eq!(items[1], Value::String("middle".into()));
1074 assert_eq!(items[2], Value::String("last".into()));
1075 }
1076
1077 #[test]
1078 fn test_encode_json_object_schema_reuse_with_extra_fields() {
1079 let json = json!({
1080 "name": "Alice",
1081 "age": 25,
1082 "active": true });
1084
1085 let fields = vec![
1087 StructField::new(
1088 "name".to_string(),
1089 ConcreteDataType::string_datatype(),
1090 true,
1091 ),
1092 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1093 ];
1094 let struct_type = StructType::new(Arc::new(fields));
1095
1096 let result = encode_json_object_with_context(
1097 json.as_object().unwrap().clone(),
1098 Some(&struct_type),
1099 &JsonContext {
1100 key_path: String::new(),
1101 settings: &JsonStructureSettings::Structured(None),
1102 },
1103 )
1104 .unwrap();
1105
1106 let struct_fields = result.struct_type().fields();
1108 assert_eq!(struct_fields[0].name(), "name");
1109 assert_eq!(struct_fields[1].name(), "age");
1110 assert_eq!(struct_fields[2].name(), "active");
1111
1112 let items = result.items();
1114 assert_eq!(items[0], Value::String("Alice".into()));
1115 assert_eq!(items[1], Value::Int64(25));
1116 assert_eq!(items[2], Value::Boolean(true));
1117 }
1118
1119 #[test]
1120 fn test_encode_json_object_missing_schema_fields() {
1121 let json = json!({
1122 "name": "Bob"
1123 });
1125
1126 let fields = vec![
1128 StructField::new(
1129 "name".to_string(),
1130 ConcreteDataType::string_datatype(),
1131 true,
1132 ),
1133 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1134 ];
1135 let struct_type = StructType::new(Arc::new(fields));
1136
1137 let result = encode_json_object_with_context(
1138 json.as_object().unwrap().clone(),
1139 Some(&struct_type),
1140 &JsonContext {
1141 key_path: String::new(),
1142 settings: &JsonStructureSettings::Structured(None),
1143 },
1144 )
1145 .unwrap();
1146
1147 let struct_fields = result.struct_type().fields();
1149 assert_eq!(struct_fields[0].name(), "name");
1150 assert_eq!(struct_fields[1].name(), "age");
1151
1152 let items = result.items();
1154 assert_eq!(items[0], Value::String("Bob".into()));
1155 assert_eq!(items[1], Value::Null);
1156 }
1157
1158 #[test]
1159 fn test_json_structure_settings_structured() {
1160 let json = json!({
1161 "name": "Eve",
1162 "score": 95
1163 });
1164
1165 let settings = JsonStructureSettings::Structured(None);
1166 let result = settings.encode(json).unwrap().into_json_inner().unwrap();
1167
1168 if let Value::Struct(struct_value) = result {
1169 assert_eq!(struct_value.items().len(), 2);
1170 } else {
1171 panic!("Expected Struct value");
1172 }
1173 }
1174
1175 #[test]
1176 fn test_encode_json_array_with_item_type() {
1177 let json = json!([1, 2, 3]);
1178 let item_type = Arc::new(ConcreteDataType::int8_datatype());
1179 let list_type = ListType::new(item_type.clone());
1180 let concrete_type = ConcreteDataType::List(list_type);
1181 let settings = JsonStructureSettings::Structured(None);
1182 let result = settings
1183 .encode_with_type(json, Some(&concrete_type))
1184 .unwrap()
1185 .into_json_inner()
1186 .unwrap();
1187
1188 if let Value::List(list_value) = result {
1189 assert_eq!(list_value.items().len(), 3);
1190 assert_eq!(list_value.items()[0], Value::Int8(1));
1191 assert_eq!(list_value.items()[1], Value::Int8(2));
1192 assert_eq!(list_value.items()[2], Value::Int8(3));
1193 assert_eq!(list_value.datatype(), item_type);
1194 } else {
1195 panic!("Expected List value");
1196 }
1197 }
1198
1199 #[test]
1200 fn test_encode_json_array_empty_with_item_type() {
1201 let json = json!([]);
1202 let item_type = Arc::new(ConcreteDataType::string_datatype());
1203 let list_type = ListType::new(item_type.clone());
1204 let concrete_type = ConcreteDataType::List(list_type);
1205 let settings = JsonStructureSettings::Structured(None);
1206 let result = settings
1207 .encode_with_type(json, Some(&concrete_type))
1208 .unwrap()
1209 .into_json_inner()
1210 .unwrap();
1211
1212 if let Value::List(list_value) = result {
1213 assert_eq!(list_value.items().len(), 0);
1214 assert_eq!(list_value.datatype(), item_type);
1215 } else {
1216 panic!("Expected List value");
1217 }
1218 }
1219
1220 #[cfg(test)]
1221 mod decode_tests {
1222 use serde_json::json;
1223
1224 use super::*;
1225
1226 #[test]
1227 fn test_decode_primitive_values() {
1228 let settings = JsonStructureSettings::Structured(None);
1229
1230 let result = settings.decode(Value::Null).unwrap();
1232 assert_eq!(result, Json::Null);
1233
1234 let result = settings.decode(Value::Boolean(true)).unwrap();
1236 assert_eq!(result, Json::Bool(true));
1237
1238 let result = settings.decode(Value::Int64(42)).unwrap();
1240 assert_eq!(result, Json::from(42));
1241
1242 let result = settings.decode(Value::Float64(OrderedFloat(3.16))).unwrap();
1244 assert_eq!(result, Json::from(3.16));
1245
1246 let result = settings.decode(Value::String("hello".into())).unwrap();
1248 assert_eq!(result, Json::String("hello".to_string()));
1249 }
1250
1251 #[test]
1252 fn test_decode_struct() {
1253 let settings = JsonStructureSettings::Structured(None);
1254
1255 let struct_value = StructValue::new(
1256 vec![
1257 Value::String("Alice".into()),
1258 Value::Int64(25),
1259 Value::Boolean(true),
1260 ],
1261 StructType::new(Arc::new(vec![
1262 StructField::new(
1263 "name".to_string(),
1264 ConcreteDataType::string_datatype(),
1265 true,
1266 ),
1267 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1268 StructField::new(
1269 "active".to_string(),
1270 ConcreteDataType::boolean_datatype(),
1271 true,
1272 ),
1273 ])),
1274 );
1275
1276 let result = settings.decode(Value::Struct(struct_value)).unwrap();
1277 let expected = json!({
1278 "name": "Alice",
1279 "age": 25,
1280 "active": true
1281 });
1282 assert_eq!(result, expected);
1283 }
1284
1285 #[test]
1286 fn test_decode_list() {
1287 let settings = JsonStructureSettings::Structured(None);
1288
1289 let list_value = ListValue::new(
1290 vec![Value::Int64(1), Value::Int64(2), Value::Int64(3)],
1291 Arc::new(ConcreteDataType::int64_datatype()),
1292 );
1293
1294 let result = settings.decode(Value::List(list_value)).unwrap();
1295 let expected = json!([1, 2, 3]);
1296 assert_eq!(result, expected);
1297 }
1298
1299 #[test]
1300 fn test_decode_nested_structure() {
1301 let settings = JsonStructureSettings::Structured(None);
1302
1303 let inner_struct = StructValue::new(
1304 vec![Value::String("Alice".into()), Value::Int64(25)],
1305 StructType::new(Arc::new(vec![
1306 StructField::new(
1307 "name".to_string(),
1308 ConcreteDataType::string_datatype(),
1309 true,
1310 ),
1311 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1312 ])),
1313 );
1314
1315 let score_list_item_type = Arc::new(ConcreteDataType::int64_datatype());
1316 let outer_struct = StructValue::new(
1317 vec![
1318 Value::Struct(inner_struct),
1319 Value::List(ListValue::new(
1320 vec![Value::Int64(95), Value::Int64(87)],
1321 score_list_item_type.clone(),
1322 )),
1323 ],
1324 StructType::new(Arc::new(vec![
1325 StructField::new(
1326 "user".to_string(),
1327 ConcreteDataType::Struct(StructType::new(Arc::new(vec![
1328 StructField::new(
1329 "name".to_string(),
1330 ConcreteDataType::string_datatype(),
1331 true,
1332 ),
1333 StructField::new(
1334 "age".to_string(),
1335 ConcreteDataType::int64_datatype(),
1336 true,
1337 ),
1338 ]))),
1339 true,
1340 ),
1341 StructField::new(
1342 "scores".to_string(),
1343 ConcreteDataType::List(ListType::new(score_list_item_type.clone())),
1344 true,
1345 ),
1346 ])),
1347 );
1348
1349 let result = settings.decode(Value::Struct(outer_struct)).unwrap();
1350 let expected = json!({
1351 "user": {
1352 "name": "Alice",
1353 "age": 25
1354 },
1355 "scores": [95, 87]
1356 });
1357 assert_eq!(result, expected);
1358 }
1359
1360 #[test]
1361 fn test_decode_unstructured_raw() {
1362 let settings = JsonStructureSettings::UnstructuredRaw;
1363
1364 let json_str = r#"{"name": "Bob", "age": 30}"#;
1365 let value = Value::String(json_str.into());
1366
1367 let result = settings.decode(value).unwrap();
1368 let expected: Json = serde_json::from_str(json_str).unwrap();
1369 assert_eq!(result, expected);
1370 }
1371
1372 #[test]
1373 fn test_decode_unstructured_raw_struct_format() {
1374 let settings = JsonStructureSettings::UnstructuredRaw;
1375
1376 let json_str = r#"{"name": "Bob", "age": 30}"#;
1377 let struct_value = StructValue::new(
1378 vec![Value::String(json_str.into())],
1379 StructType::new(Arc::new(vec![StructField::new(
1380 JsonStructureSettings::RAW_FIELD.to_string(),
1381 ConcreteDataType::string_datatype(),
1382 true,
1383 )])),
1384 );
1385 let value = Value::Struct(struct_value);
1386
1387 let result = settings.decode(value).unwrap();
1388 let expected: Json = serde_json::from_str(json_str).unwrap();
1389 assert_eq!(result, expected);
1390 }
1391
1392 #[test]
1393 fn test_decode_partial_unstructured() {
1394 let mut unstructured_keys = HashSet::new();
1395 unstructured_keys.insert("user.metadata".to_string());
1396
1397 let settings = JsonStructureSettings::PartialUnstructuredByKey {
1398 fields: None,
1399 unstructured_keys,
1400 };
1401
1402 let metadata_json = r#"{"preferences": {"theme": "dark"}, "history": [1, 2, 3]}"#;
1403
1404 let struct_value = StructValue::new(
1405 vec![
1406 Value::String("Alice".into()),
1407 Value::String(metadata_json.into()),
1408 ],
1409 StructType::new(Arc::new(vec![
1410 StructField::new(
1411 "name".to_string(),
1412 ConcreteDataType::string_datatype(),
1413 true,
1414 ),
1415 StructField::new(
1416 "metadata".to_string(),
1417 ConcreteDataType::string_datatype(),
1418 true,
1419 ),
1420 ])),
1421 );
1422
1423 let result = settings.decode(Value::Struct(struct_value)).unwrap();
1424
1425 if let Json::Object(obj) = result {
1426 assert_eq!(obj.get("name"), Some(&Json::String("Alice".to_string())));
1427
1428 if let Some(Json::String(metadata_str)) = obj.get("metadata") {
1429 let metadata: Json = serde_json::from_str(metadata_str).unwrap();
1430 let expected_metadata: Json = serde_json::from_str(metadata_json).unwrap();
1431 assert_eq!(metadata, expected_metadata);
1432 } else {
1433 panic!("Expected metadata to be unstructured string");
1434 }
1435 } else {
1436 panic!("Expected object result");
1437 }
1438 }
1439
1440 #[test]
1441 fn test_decode_missing_fields() {
1442 let settings = JsonStructureSettings::Structured(None);
1443
1444 let struct_value = StructValue::new(
1446 vec![
1447 Value::String("Bob".into()),
1448 Value::Null, ],
1450 StructType::new(Arc::new(vec![
1451 StructField::new(
1452 "name".to_string(),
1453 ConcreteDataType::string_datatype(),
1454 true,
1455 ),
1456 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1457 ])),
1458 );
1459
1460 let result = settings.decode(Value::Struct(struct_value)).unwrap();
1461 let expected = json!({
1462 "name": "Bob",
1463 "age": null
1464 });
1465 assert_eq!(result, expected);
1466 }
1467 }
1468
1469 #[test]
1470 fn test_encode_json_with_concrete_type() {
1471 let settings = JsonStructureSettings::Structured(None);
1472
1473 let json = Json::from(42);
1475 let result = settings
1476 .encode_with_type(json, Some(&ConcreteDataType::int64_datatype()))
1477 .unwrap()
1478 .into_json_inner()
1479 .unwrap();
1480 assert_eq!(result, Value::Int64(42));
1481
1482 let json = Json::String("hello".to_string());
1484 let result = settings
1485 .encode_with_type(json, Some(&ConcreteDataType::string_datatype()))
1486 .unwrap()
1487 .into_json_inner()
1488 .unwrap();
1489 assert_eq!(result, Value::String("hello".into()));
1490
1491 let json = Json::Bool(true);
1493 let result = settings
1494 .encode_with_type(json, Some(&ConcreteDataType::boolean_datatype()))
1495 .unwrap()
1496 .into_json_inner()
1497 .unwrap();
1498 assert_eq!(result, Value::Boolean(true));
1499 }
1500
1501 #[test]
1502 fn test_encode_json_with_mismatched_type() {
1503 let json = Json::from(42);
1505 let settings = JsonStructureSettings::Structured(None);
1506 let result = settings.encode_with_type(json, Some(&ConcreteDataType::string_datatype()));
1507 assert!(result.is_ok()); let json = json!({"name": "test"});
1511 let result = settings.encode_with_type(json, Some(&ConcreteDataType::int64_datatype()));
1512 assert!(result.is_err()); }
1514
1515 #[test]
1516 fn test_encode_json_array_with_list_type() {
1517 let json = json!([1, 2, 3]);
1518 let item_type = Arc::new(ConcreteDataType::int64_datatype());
1519 let list_type = ListType::new(item_type.clone());
1520 let concrete_type = ConcreteDataType::List(list_type);
1521
1522 let settings = JsonStructureSettings::Structured(None);
1523 let result = settings
1524 .encode_with_type(json, Some(&concrete_type))
1525 .unwrap()
1526 .into_json_inner()
1527 .unwrap();
1528
1529 if let Value::List(list_value) = result {
1530 assert_eq!(list_value.items().len(), 3);
1531 assert_eq!(list_value.items()[0], Value::Int64(1));
1532 assert_eq!(list_value.items()[1], Value::Int64(2));
1533 assert_eq!(list_value.items()[2], Value::Int64(3));
1534 assert_eq!(list_value.datatype(), item_type);
1535 } else {
1536 panic!("Expected List value");
1537 }
1538 }
1539
1540 #[test]
1541 fn test_encode_json_non_collection_with_type() {
1542 let json = Json::Null;
1544 let settings = JsonStructureSettings::Structured(None);
1545 let result = settings
1546 .encode_with_type(json.clone(), Some(&ConcreteDataType::null_datatype()))
1547 .unwrap()
1548 .into_json_inner()
1549 .unwrap();
1550 assert_eq!(result, Value::Null);
1551
1552 let json = Json::from(3.15);
1554 let result = settings
1555 .encode_with_type(json, Some(&ConcreteDataType::float64_datatype()))
1556 .unwrap()
1557 .into_json_inner()
1558 .unwrap();
1559 match result {
1560 Value::Float64(f) => assert_eq!(f.0, 3.15),
1561 _ => panic!("Expected Float64"),
1562 }
1563 }
1564
1565 #[test]
1566 fn test_encode_json_large_unsigned_integer() {
1567 let json = Json::from(u64::MAX / 2);
1569 let settings = JsonStructureSettings::Structured(None);
1570 let result = settings
1571 .encode_with_type(json, None)
1572 .unwrap()
1573 .into_json_inner()
1574 .unwrap();
1575 assert_eq!(result, Value::Int64((u64::MAX / 2) as i64));
1576
1577 let json = Json::from(u64::MAX);
1579 let result = settings
1580 .encode_with_type(json, None)
1581 .unwrap()
1582 .into_json_inner()
1583 .unwrap();
1584 assert_eq!(result, Value::UInt64(u64::MAX));
1585 }
1586
1587 #[test]
1588 fn test_json_structure_settings_unstructured_raw() {
1589 let json = json!({
1590 "name": "Frank",
1591 "score": 88
1592 });
1593
1594 let settings = JsonStructureSettings::UnstructuredRaw;
1595 let result = settings.encode(json).unwrap().into_json_inner().unwrap();
1596
1597 if let Value::Struct(struct_value) = result {
1598 assert_eq!(struct_value.struct_type().fields().len(), 1);
1599 let field = &struct_value.struct_type().fields()[0];
1600 assert_eq!(field.name(), JsonStructureSettings::RAW_FIELD);
1601 assert_eq!(field.data_type(), &ConcreteDataType::string_datatype());
1602
1603 let items = struct_value.items();
1604 assert_eq!(items.len(), 1);
1605 if let Value::String(s) = &items[0] {
1606 let json_str = s.as_utf8();
1607 assert!(json_str.contains("\"name\":\"Frank\""));
1608 assert!(json_str.contains("\"score\":88"));
1609 } else {
1610 panic!("Expected String value in _raw field");
1611 }
1612 } else {
1613 panic!("Expected Struct value");
1614 }
1615 }
1616
1617 #[test]
1618 fn test_json_structure_settings_unstructured_raw_with_type() {
1619 let json = json!({
1620 "name": "Grace",
1621 "age": 30,
1622 "active": true
1623 });
1624
1625 let settings = JsonStructureSettings::UnstructuredRaw;
1626
1627 let result = settings
1629 .encode(json.clone())
1630 .unwrap()
1631 .into_json_inner()
1632 .unwrap();
1633 if let Value::Struct(s) = result {
1634 if let Value::String(json_str) = &s.items()[0] {
1635 let json_str = json_str.as_utf8();
1636 assert!(json_str.contains("\"name\":\"Grace\""));
1637 assert!(json_str.contains("\"age\":30"));
1638 assert!(json_str.contains("\"active\":true"));
1639 } else {
1640 panic!("Expected String value in _raw field");
1641 }
1642 } else {
1643 panic!("Expected Struct value for encode");
1644 }
1645
1646 let struct_type = StructType::new(Arc::new(vec![
1648 StructField::new(
1649 "name".to_string(),
1650 ConcreteDataType::string_datatype(),
1651 true,
1652 ),
1653 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1654 StructField::new(
1655 "active".to_string(),
1656 ConcreteDataType::boolean_datatype(),
1657 true,
1658 ),
1659 ]));
1660 let concrete_type = ConcreteDataType::Struct(struct_type);
1661
1662 let result2 = settings
1663 .encode_with_type(json, Some(&concrete_type))
1664 .unwrap()
1665 .into_json_inner()
1666 .unwrap();
1667 if let Value::Struct(s) = result2 {
1668 if let Value::String(json_str) = &s.items()[0] {
1669 let json_str = json_str.as_utf8();
1670 assert!(json_str.contains("\"name\":\"Grace\""));
1671 assert!(json_str.contains("\"age\":30"));
1672 assert!(json_str.contains("\"active\":true"));
1673 } else {
1674 panic!("Expected String value for _raw field");
1675 }
1676 } else {
1677 panic!("Expected String value for encode_with_type");
1678 }
1679
1680 let nested_json = json!({
1682 "user": {
1683 "profile": {
1684 "name": "Alice",
1685 "settings": {"theme": "dark"}
1686 }
1687 }
1688 });
1689
1690 let result3 = settings
1691 .encode(nested_json)
1692 .unwrap()
1693 .into_json_inner()
1694 .unwrap();
1695 if let Value::Struct(s) = result3 {
1696 if let Value::String(json_str) = &s.items()[0] {
1697 let json_str = json_str.as_utf8();
1698 assert!(json_str.contains("\"user\""));
1699 assert!(json_str.contains("\"profile\""));
1700 assert!(json_str.contains("\"name\":\"Alice\""));
1701 assert!(json_str.contains("\"settings\""));
1702 assert!(json_str.contains("\"theme\":\"dark\""));
1703 } else {
1704 panic!("Expected String value for _raw field");
1705 }
1706 } else {
1707 panic!("Expected String value for nested JSON");
1708 }
1709
1710 let array_json = json!([1, "hello", true, 3.15]);
1712 let result4 = settings
1713 .encode(array_json)
1714 .unwrap()
1715 .into_json_inner()
1716 .unwrap();
1717 if let Value::Struct(s) = result4 {
1718 if let Value::String(json_str) = &s.items()[0] {
1719 let json_str = json_str.as_utf8();
1720 assert!(json_str.contains("[1,\"hello\",true,3.15]"));
1721 } else {
1722 panic!("Expected String value for _raw field")
1723 }
1724 } else {
1725 panic!("Expected String value for array JSON");
1726 }
1727 }
1728
1729 #[test]
1730 fn test_encode_json_with_context_partial_unstructured() {
1731 let json = json!({
1732 "user": {
1733 "name": "Alice",
1734 "metadata": {
1735 "preferences": {"theme": "dark"},
1736 "history": [1, 2, 3]
1737 }
1738 }
1739 });
1740
1741 let mut unstructured_keys = HashSet::new();
1742 unstructured_keys.insert("user.metadata".to_string());
1743
1744 let settings = JsonStructureSettings::PartialUnstructuredByKey {
1745 fields: None,
1746 unstructured_keys,
1747 };
1748 let result = settings.encode(json).unwrap().into_json_inner().unwrap();
1749
1750 if let Value::Struct(struct_value) = result {
1751 let items = struct_value.items();
1752 let struct_type = struct_value.struct_type();
1753
1754 let user_index = struct_type
1756 .fields()
1757 .iter()
1758 .position(|f| f.name() == "user")
1759 .unwrap();
1760 if let Value::Struct(user_struct) = &items[user_index] {
1761 let user_items = user_struct.items();
1762 let fields = user_struct.struct_type().fields();
1763 let user_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
1764
1765 let name_index = user_fields.iter().position(|&f| f == "name").unwrap();
1767 assert_eq!(user_items[name_index], Value::String("Alice".into()));
1768
1769 let metadata_index = user_fields.iter().position(|&f| f == "metadata").unwrap();
1771 if let Value::String(metadata_str) = &user_items[metadata_index] {
1772 let json_str = metadata_str.as_utf8();
1773 assert!(json_str.contains("\"preferences\""));
1774 assert!(json_str.contains("\"history\""));
1775 } else {
1776 panic!("Expected String value for metadata field");
1777 }
1778 } else {
1779 panic!("Expected Struct value for user field");
1780 }
1781 } else {
1782 panic!("Expected Struct value");
1783 }
1784 }
1785
1786 #[test]
1787 fn test_decode_struct_structured() {
1788 let settings = JsonStructureSettings::Structured(None);
1790
1791 let original_struct = StructValue::new(
1792 vec![
1793 Value::String("Alice".into()),
1794 Value::Int64(25),
1795 Value::Boolean(true),
1796 ],
1797 StructType::new(Arc::new(vec![
1798 StructField::new(
1799 "name".to_string(),
1800 ConcreteDataType::string_datatype(),
1801 true,
1802 ),
1803 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1804 StructField::new(
1805 "active".to_string(),
1806 ConcreteDataType::boolean_datatype(),
1807 true,
1808 ),
1809 ])),
1810 );
1811
1812 let decoded_struct = settings.decode_struct(original_struct.clone()).unwrap();
1813
1814 assert_eq!(decoded_struct.items(), original_struct.items());
1816 assert_eq!(decoded_struct.struct_type(), original_struct.struct_type());
1817 }
1818
1819 #[test]
1820 fn test_decode_struct_partial_unstructured_empty_keys() {
1821 let settings = JsonStructureSettings::PartialUnstructuredByKey {
1823 fields: None,
1824 unstructured_keys: HashSet::new(),
1825 };
1826
1827 let original_struct = StructValue::new(
1828 vec![
1829 Value::String("Alice".into()),
1830 Value::Int64(25),
1831 Value::Boolean(true),
1832 ],
1833 StructType::new(Arc::new(vec![
1834 StructField::new(
1835 "name".to_string(),
1836 ConcreteDataType::string_datatype(),
1837 true,
1838 ),
1839 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
1840 StructField::new(
1841 "active".to_string(),
1842 ConcreteDataType::boolean_datatype(),
1843 true,
1844 ),
1845 ])),
1846 );
1847
1848 let decoded_struct = settings.decode_struct(original_struct.clone()).unwrap();
1849
1850 assert_eq!(decoded_struct.items(), original_struct.items());
1852 assert_eq!(decoded_struct.struct_type(), original_struct.struct_type());
1853 }
1854
1855 #[test]
1856 fn test_decode_struct_partial_unstructured() {
1857 let mut unstructured_keys = HashSet::new();
1859 unstructured_keys.insert("metadata".to_string());
1860
1861 let settings = JsonStructureSettings::PartialUnstructuredByKey {
1862 fields: Some(StructType::new(Arc::new(vec![
1863 StructField::new(
1864 "name".to_string(),
1865 ConcreteDataType::string_datatype(),
1866 true,
1867 ),
1868 StructField::new(
1869 "metadata".to_string(),
1870 ConcreteDataType::string_datatype(),
1871 true,
1872 ),
1873 ]))),
1874 unstructured_keys,
1875 };
1876
1877 let encoded_struct = StructValue::new(
1879 vec![
1880 Value::String("Alice".into()),
1881 Value::String(r#"{"preferences":{"theme":"dark"},"history":[1,2,3]}"#.into()),
1882 ],
1883 StructType::new(Arc::new(vec![
1884 StructField::new(
1885 "name".to_string(),
1886 ConcreteDataType::string_datatype(),
1887 true,
1888 ),
1889 StructField::new(
1890 "metadata".to_string(),
1891 ConcreteDataType::string_datatype(),
1892 true,
1893 ),
1894 ])),
1895 );
1896
1897 let decoded_struct = settings.decode_struct(encoded_struct).unwrap();
1898
1899 assert_eq!(decoded_struct.items()[0], Value::String("Alice".into()));
1901
1902 if let Value::Struct(metadata_struct) = &decoded_struct.items()[1] {
1904 let fields = metadata_struct.struct_type().fields();
1905 let metadata_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
1906
1907 assert!(metadata_fields.contains(&"preferences"));
1908 assert!(metadata_fields.contains(&"history"));
1909 } else {
1910 panic!("Expected metadata to be decoded as structured value");
1911 }
1912 }
1913
1914 #[test]
1915 fn test_decode_struct_nested_unstructured() {
1916 let mut unstructured_keys = HashSet::new();
1918 unstructured_keys.insert("user.metadata".to_string());
1919
1920 let settings = JsonStructureSettings::PartialUnstructuredByKey {
1921 fields: None,
1922 unstructured_keys,
1923 };
1924
1925 let user_struct = StructValue::new(
1927 vec![
1928 Value::String("Alice".into()),
1929 Value::String(r#"{"preferences":{"theme":"dark"},"history":[1,2,3]}"#.into()),
1930 ],
1931 StructType::new(Arc::new(vec![
1932 StructField::new(
1933 "name".to_string(),
1934 ConcreteDataType::string_datatype(),
1935 true,
1936 ),
1937 StructField::new(
1938 "metadata".to_string(),
1939 ConcreteDataType::string_datatype(),
1940 true,
1941 ),
1942 ])),
1943 );
1944
1945 let encoded_struct = StructValue::new(
1946 vec![Value::Struct(user_struct)],
1947 StructType::new(Arc::new(vec![StructField::new(
1948 "user".to_string(),
1949 ConcreteDataType::struct_datatype(StructType::new(Arc::new(vec![]))),
1950 true,
1951 )])),
1952 );
1953
1954 let decoded_struct = settings.decode_struct(encoded_struct).unwrap();
1955
1956 if let Value::Struct(decoded_user) = &decoded_struct.items()[0] {
1958 if let Value::Struct(metadata_struct) = &decoded_user.items()[1] {
1959 let fields = metadata_struct.struct_type().fields();
1960 let metadata_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
1961
1962 assert!(metadata_fields.contains(&"preferences"));
1963 assert!(metadata_fields.contains(&"history"));
1964
1965 let preference_index = metadata_fields
1966 .iter()
1967 .position(|&field| field == "preferences")
1968 .unwrap();
1969 let history_index = metadata_fields
1970 .iter()
1971 .position(|&field| field == "history")
1972 .unwrap();
1973
1974 if let Value::Struct(preferences_struct) =
1976 &metadata_struct.items()[preference_index]
1977 {
1978 let fields = preferences_struct.struct_type().fields();
1979 let pref_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
1980 assert!(pref_fields.contains(&"theme"));
1981 } else {
1982 panic!("Expected preferences to be decoded as structured value");
1983 }
1984
1985 if let Value::List(history_list) = &metadata_struct.items()[history_index] {
1987 assert_eq!(history_list.items().len(), 3);
1988 } else {
1989 panic!("Expected history to be decoded as list value");
1990 }
1991 } else {
1992 panic!("Expected metadata to be decoded as structured value");
1993 }
1994 } else {
1995 panic!("Expected user to be decoded as structured value");
1996 }
1997 }
1998
1999 #[test]
2000 fn test_decode_struct_unstructured_raw() {
2001 let settings = JsonStructureSettings::UnstructuredRaw;
2003
2004 let encoded_struct = StructValue::new(
2006 vec![Value::String(
2007 r#"{"name":"Alice","age":25,"active":true}"#.into(),
2008 )],
2009 StructType::new(Arc::new(vec![StructField::new(
2010 "_raw".to_string(),
2011 ConcreteDataType::string_datatype(),
2012 true,
2013 )])),
2014 );
2015
2016 let decoded_struct = settings.decode_struct(encoded_struct).unwrap();
2017
2018 let fields = decoded_struct.struct_type().fields();
2020 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2021
2022 assert!(decoded_fields.contains(&"name"));
2023 assert!(decoded_fields.contains(&"age"));
2024 assert!(decoded_fields.contains(&"active"));
2025
2026 let name_index = decoded_fields.iter().position(|&f| f == "name").unwrap();
2028 let age_index = decoded_fields.iter().position(|&f| f == "age").unwrap();
2029 let active_index = decoded_fields.iter().position(|&f| f == "active").unwrap();
2030
2031 assert_eq!(
2032 decoded_struct.items()[name_index],
2033 Value::String("Alice".into())
2034 );
2035 assert_eq!(decoded_struct.items()[age_index], Value::Int64(25));
2036 assert_eq!(decoded_struct.items()[active_index], Value::Boolean(true));
2037 }
2038
2039 #[test]
2040 fn test_decode_struct_unstructured_raw_invalid_format() {
2041 let settings = JsonStructureSettings::UnstructuredRaw;
2043
2044 let invalid_struct = StructValue::new(
2046 vec![Value::String("Alice".into()), Value::Int64(25)],
2047 StructType::new(Arc::new(vec![
2048 StructField::new(
2049 "name".to_string(),
2050 ConcreteDataType::string_datatype(),
2051 true,
2052 ),
2053 StructField::new("age".to_string(), ConcreteDataType::int64_datatype(), true),
2054 ])),
2055 );
2056
2057 let result = settings.decode_struct(invalid_struct);
2059 assert!(result.is_err());
2060 assert!(
2061 result
2062 .unwrap_err()
2063 .to_string()
2064 .contains("UnstructuredRaw value must be stored as struct with single _raw field")
2065 );
2066 }
2067
2068 #[test]
2069 fn test_decode_struct_unstructured_raw_primitive_value() {
2070 let settings = JsonStructureSettings::UnstructuredRaw;
2072
2073 let string_struct = StructValue::new(
2075 vec![Value::String("\"hello world\"".into())],
2076 StructType::new(Arc::new(vec![StructField::new(
2077 "_raw".to_string(),
2078 ConcreteDataType::string_datatype(),
2079 true,
2080 )])),
2081 );
2082
2083 let decoded_struct = settings.decode_struct(string_struct).unwrap();
2084 let fields = decoded_struct.struct_type().fields();
2085 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2086 assert!(decoded_fields.contains(&"value"));
2087 assert_eq!(
2088 decoded_struct.items()[0],
2089 Value::String("hello world".into())
2090 );
2091
2092 let number_struct = StructValue::new(
2094 vec![Value::String("42".into())],
2095 StructType::new(Arc::new(vec![StructField::new(
2096 "_raw".to_string(),
2097 ConcreteDataType::string_datatype(),
2098 true,
2099 )])),
2100 );
2101
2102 let decoded_struct = settings.decode_struct(number_struct).unwrap();
2103 let fields = decoded_struct.struct_type().fields();
2104 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2105 assert!(decoded_fields.contains(&"value"));
2106 assert_eq!(decoded_struct.items()[0], Value::Int64(42));
2107
2108 let bool_struct = StructValue::new(
2110 vec![Value::String("true".into())],
2111 StructType::new(Arc::new(vec![StructField::new(
2112 "_raw".to_string(),
2113 ConcreteDataType::string_datatype(),
2114 true,
2115 )])),
2116 );
2117
2118 let decoded_struct = settings.decode_struct(bool_struct).unwrap();
2119 let fields = decoded_struct.struct_type().fields();
2120 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2121 assert!(decoded_fields.contains(&"value"));
2122 assert_eq!(decoded_struct.items()[0], Value::Boolean(true));
2123
2124 let null_struct = StructValue::new(
2126 vec![Value::String("null".into())],
2127 StructType::new(Arc::new(vec![StructField::new(
2128 "_raw".to_string(),
2129 ConcreteDataType::string_datatype(),
2130 true,
2131 )])),
2132 );
2133
2134 let decoded_struct = settings.decode_struct(null_struct).unwrap();
2135 let fields = decoded_struct.struct_type().fields();
2136 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2137 assert!(decoded_fields.contains(&"value"));
2138 assert_eq!(decoded_struct.items()[0], Value::Null);
2139 }
2140
2141 #[test]
2142 fn test_decode_struct_unstructured_raw_array() {
2143 let settings = JsonStructureSettings::UnstructuredRaw;
2145
2146 let array_struct = StructValue::new(
2148 vec![Value::String("[1, \"hello\", true, 3.15]".into())],
2149 StructType::new(Arc::new(vec![StructField::new(
2150 "_raw".to_string(),
2151 ConcreteDataType::string_datatype(),
2152 true,
2153 )])),
2154 );
2155
2156 let decoded_struct = settings.decode_struct(array_struct).unwrap();
2157 let fields = decoded_struct.struct_type().fields();
2158 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2159 assert!(decoded_fields.contains(&"value"));
2160
2161 if let Value::List(list_value) = &decoded_struct.items()[0] {
2162 assert_eq!(list_value.items().len(), 4);
2163 assert_eq!(list_value.items()[0], Value::Int64(1));
2164 assert_eq!(list_value.items()[1], Value::String("hello".into()));
2165 assert_eq!(list_value.items()[2], Value::Boolean(true));
2166 assert_eq!(list_value.items()[3], Value::Float64(OrderedFloat(3.15)));
2167 } else {
2168 panic!("Expected array to be decoded as ListValue");
2169 }
2170 }
2171
2172 #[test]
2173 fn test_decode_struct_comprehensive_flow() {
2174 let mut unstructured_keys = HashSet::new();
2177 unstructured_keys.insert("metadata".to_string());
2178 unstructured_keys.insert("user.profile.settings".to_string());
2179
2180 let settings = JsonStructureSettings::PartialUnstructuredByKey {
2181 fields: None,
2182 unstructured_keys,
2183 };
2184
2185 let original_json = json!({
2187 "name": "Alice",
2188 "age": 25,
2189 "metadata": {
2190 "tags": ["admin", "premium"],
2191 "preferences": {
2192 "theme": "dark",
2193 "notifications": true
2194 }
2195 },
2196 "user": {
2197 "profile": {
2198 "name": "Alice Smith",
2199 "settings": {
2200 "language": "en",
2201 "timezone": "UTC"
2202 }
2203 },
2204 "active": true
2205 }
2206 });
2207
2208 let encoded_value = settings
2210 .encode(original_json)
2211 .unwrap()
2212 .into_json_inner()
2213 .unwrap();
2214
2215 if let Value::Struct(encoded_struct) = encoded_value {
2217 let fields = encoded_struct.struct_type().fields();
2218 let fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2219
2220 assert!(fields.contains(&"name"));
2221 assert!(fields.contains(&"age"));
2222 assert!(fields.contains(&"metadata"));
2223 assert!(fields.contains(&"user"));
2224
2225 let metadata_index = fields.iter().position(|&f| f == "metadata").unwrap();
2227 if let Value::String(_) = encoded_struct.items()[metadata_index] {
2228 } else {
2230 panic!("Expected metadata to be encoded as string (unstructured)");
2231 }
2232
2233 let user_index = fields.iter().position(|&f| f == "user").unwrap();
2235 if let Value::Struct(user_struct) = &encoded_struct.items()[user_index] {
2236 let fields = user_struct.struct_type().fields();
2237 let user_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2238
2239 let profile_index = user_fields.iter().position(|&f| f == "profile").unwrap();
2240 if let Value::Struct(profile_struct) = &user_struct.items()[profile_index] {
2241 let fields = profile_struct.struct_type().fields();
2242 let profile_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2243
2244 let settings_index = profile_fields
2245 .iter()
2246 .position(|&f| f == "settings")
2247 .unwrap();
2248 if let Value::String(_) = &profile_struct.items()[settings_index] {
2249 } else {
2251 panic!(
2252 "Expected user.profile.settings to be encoded as string (unstructured)"
2253 );
2254 }
2255 } else {
2256 panic!("Expected user.profile to be a struct");
2257 }
2258 } else {
2259 panic!("Expected user to be a struct");
2260 }
2261
2262 let decoded_struct = settings.decode_struct(encoded_struct).unwrap();
2264
2265 let fields = decoded_struct.struct_type().fields();
2267 let decoded_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2268
2269 assert!(decoded_fields.contains(&"name"));
2270 assert!(decoded_fields.contains(&"age"));
2271 assert!(decoded_fields.contains(&"metadata"));
2272 assert!(decoded_fields.contains(&"user"));
2273
2274 let metadata_index = decoded_fields
2276 .iter()
2277 .position(|&f| f == "metadata")
2278 .unwrap();
2279 if let Value::Struct(metadata_struct) = &decoded_struct.items()[metadata_index] {
2280 let fields = metadata_struct.struct_type().fields();
2281 let metadata_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2282
2283 assert!(metadata_fields.contains(&"tags"));
2284 assert!(metadata_fields.contains(&"preferences"));
2285
2286 let preferences_index = metadata_fields
2288 .iter()
2289 .position(|&f| f == "preferences")
2290 .unwrap();
2291 if let Value::Struct(prefs_struct) = &metadata_struct.items()[preferences_index] {
2292 let fields = prefs_struct.struct_type().fields();
2293 let prefs_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2294
2295 assert!(prefs_fields.contains(&"theme"));
2296 assert!(prefs_fields.contains(&"notifications"));
2297 } else {
2298 panic!("Expected metadata.preferences to be a struct");
2299 }
2300 } else {
2301 panic!("Expected metadata to be decoded as struct");
2302 }
2303
2304 let user_index = decoded_fields.iter().position(|&f| f == "user").unwrap();
2306 if let Value::Struct(user_struct) = &decoded_struct.items()[user_index] {
2307 let fields = user_struct.struct_type().fields();
2308 let user_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2309
2310 let profile_index = user_fields.iter().position(|&f| f == "profile").unwrap();
2311 if let Value::Struct(profile_struct) = &user_struct.items()[profile_index] {
2312 let fields = profile_struct.struct_type().fields();
2313 let profile_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2314
2315 let settings_index = profile_fields
2316 .iter()
2317 .position(|&f| f == "settings")
2318 .unwrap();
2319 if let Value::Struct(settings_struct) = &profile_struct.items()[settings_index]
2320 {
2321 let fields = settings_struct.struct_type().fields();
2322 let settings_fields: Vec<&str> = fields.iter().map(|f| f.name()).collect();
2323
2324 assert!(settings_fields.contains(&"language"));
2325 assert!(settings_fields.contains(&"timezone"));
2326 } else {
2327 panic!("Expected user.profile.settings to be decoded as struct");
2328 }
2329 } else {
2330 panic!("Expected user.profile to be a struct");
2331 }
2332 } else {
2333 panic!("Expected user to be a struct");
2334 }
2335 } else {
2336 panic!("Expected encoded value to be a struct");
2337 }
2338 }
2339}