Skip to main content

datatypes/
json.rs

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