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