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