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