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