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