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