datatypes/
json.rs

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