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