Skip to main content

datatypes/json/
value.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
15use std::collections::BTreeMap;
16use std::fmt::{Display, Formatter};
17use std::hash::{Hash, Hasher};
18use std::sync::{Arc, OnceLock};
19
20use num_traits::ToPrimitive;
21use ordered_float::OrderedFloat;
22use serde::{Deserialize, Serialize};
23use serde_json::Number;
24use snafu::{OptionExt, ResultExt, ensure};
25
26use crate::Result;
27use crate::data_type::ConcreteDataType;
28use crate::error::{AlignJsonValueSnafu, SerializeSnafu};
29use crate::types::json_type::{JsonNativeType, JsonNumberType};
30use crate::types::{JsonType, StructField, StructType};
31use crate::value::{ListValue, ListValueRef, StructValue, StructValueRef, Value, ValueRef};
32
33/// Number in json, can be a positive integer, a negative integer, or a floating number.
34/// Each of which is represented as `u64`, `i64` and `f64`.
35///
36/// This follows how `serde_json` designs number.
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
38pub enum JsonNumber {
39    PosInt(u64),
40    NegInt(i64),
41    Float(OrderedFloat<f64>),
42}
43
44impl JsonNumber {
45    fn as_u64(&self) -> Option<u64> {
46        match self {
47            JsonNumber::PosInt(n) => Some(*n),
48            JsonNumber::NegInt(n) => (*n >= 0).then_some(*n as u64),
49            _ => None,
50        }
51    }
52
53    fn as_i64(&self) -> Option<i64> {
54        match self {
55            JsonNumber::PosInt(n) => (*n <= i64::MAX as u64).then_some(*n as i64),
56            JsonNumber::NegInt(n) => Some(*n),
57            _ => None,
58        }
59    }
60
61    fn as_f64(&self) -> f64 {
62        match self {
63            JsonNumber::PosInt(n) => *n as f64,
64            JsonNumber::NegInt(n) => *n as f64,
65            JsonNumber::Float(n) => n.0,
66        }
67    }
68
69    fn native_type(&self) -> JsonNativeType {
70        match self {
71            JsonNumber::PosInt(_) => JsonNativeType::u64(),
72            JsonNumber::NegInt(_) => JsonNativeType::i64(),
73            JsonNumber::Float(_) => JsonNativeType::f64(),
74        }
75    }
76}
77
78impl From<u64> for JsonNumber {
79    fn from(i: u64) -> Self {
80        Self::PosInt(i)
81    }
82}
83
84impl From<i64> for JsonNumber {
85    fn from(n: i64) -> Self {
86        Self::NegInt(n)
87    }
88}
89
90impl From<f64> for JsonNumber {
91    fn from(i: f64) -> Self {
92        Self::Float(i.into())
93    }
94}
95
96impl From<Number> for JsonNumber {
97    fn from(n: Number) -> Self {
98        if let Some(i) = n.as_i64() {
99            i.into()
100        } else if let Some(i) = n.as_u64() {
101            i.into()
102        } else {
103            n.as_f64().unwrap_or(f64::NAN).into()
104        }
105    }
106}
107
108impl Display for JsonNumber {
109    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
110        match self {
111            Self::PosInt(x) => write!(f, "{x}"),
112            Self::NegInt(x) => write!(f, "{x}"),
113            Self::Float(x) => write!(f, "{x}"),
114        }
115    }
116}
117
118/// Variants of json.
119#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
120pub enum JsonVariant {
121    #[default]
122    Null,
123    Bool(bool),
124    Number(JsonNumber),
125    String(String),
126    Array(Vec<JsonVariant>),
127    Object(BTreeMap<String, JsonVariant>),
128    /// A special "variant" value of JSON, to represent a union result of conflict JSON type values.
129    Variant(Vec<u8>),
130}
131
132impl JsonVariant {
133    pub(crate) fn as_i64(&self) -> Option<i64> {
134        match self {
135            JsonVariant::Number(n) => n.as_i64(),
136            _ => None,
137        }
138    }
139
140    pub(crate) fn as_u64(&self) -> Option<u64> {
141        match self {
142            JsonVariant::Number(n) => n.as_u64(),
143            _ => None,
144        }
145    }
146
147    pub(crate) fn as_f64(&self) -> Option<f64> {
148        match self {
149            JsonVariant::Number(n) => Some(n.as_f64()),
150            _ => None,
151        }
152    }
153
154    pub(crate) fn native_type(&self) -> JsonNativeType {
155        match self {
156            JsonVariant::Null => JsonNativeType::Null,
157            JsonVariant::Bool(_) => JsonNativeType::Bool,
158            JsonVariant::Number(n) => n.native_type(),
159            JsonVariant::String(_) => JsonNativeType::String,
160            JsonVariant::Array(array) => {
161                json_array_native_type(array.iter().map(JsonVariant::native_type))
162            }
163            JsonVariant::Object(object) => {
164                json_object_native_type(object.iter().map(|(k, v)| (k, v.native_type())))
165            }
166            JsonVariant::Variant(_) => JsonNativeType::Variant,
167        }
168    }
169
170    fn json_type(&self) -> JsonType {
171        JsonType::new_json2(self.native_type())
172    }
173
174    fn as_ref(&self) -> JsonVariantRef<'_> {
175        match self {
176            JsonVariant::Null => JsonVariantRef::Null,
177            JsonVariant::Bool(x) => (*x).into(),
178            JsonVariant::Number(x) => match x {
179                JsonNumber::PosInt(i) => (*i).into(),
180                JsonNumber::NegInt(i) => (*i).into(),
181                JsonNumber::Float(f) => (f.0).into(),
182            },
183            JsonVariant::String(x) => x.as_str().into(),
184            JsonVariant::Array(array) => {
185                JsonVariantRef::Array(array.iter().map(|x| x.as_ref()).collect())
186            }
187            JsonVariant::Object(object) => JsonVariantRef::Object(
188                object
189                    .iter()
190                    .map(|(k, v)| (k.as_str(), v.as_ref()))
191                    .collect(),
192            ),
193            JsonVariant::Variant(v) => JsonVariantRef::Variant(v),
194        }
195    }
196}
197
198impl From<()> for JsonVariant {
199    fn from(_: ()) -> Self {
200        Self::Null
201    }
202}
203
204impl From<bool> for JsonVariant {
205    fn from(v: bool) -> Self {
206        Self::Bool(v)
207    }
208}
209
210impl<T: Into<JsonNumber>> From<T> for JsonVariant {
211    fn from(v: T) -> Self {
212        Self::Number(v.into())
213    }
214}
215
216impl From<&str> for JsonVariant {
217    fn from(v: &str) -> Self {
218        Self::String(v.to_string())
219    }
220}
221
222impl From<String> for JsonVariant {
223    fn from(v: String) -> Self {
224        Self::String(v)
225    }
226}
227
228impl<const N: usize, T: Into<JsonVariant>> From<[T; N]> for JsonVariant {
229    fn from(vs: [T; N]) -> Self {
230        Self::Array(vs.into_iter().map(|x| x.into()).collect())
231    }
232}
233
234impl<K: Into<String>, V: Into<JsonVariant>, const N: usize> From<[(K, V); N]> for JsonVariant {
235    fn from(vs: [(K, V); N]) -> Self {
236        Self::Object(vs.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
237    }
238}
239
240impl From<serde_json::Value> for JsonVariant {
241    fn from(v: serde_json::Value) -> Self {
242        fn helper(v: serde_json::Value) -> JsonVariant {
243            match v {
244                serde_json::Value::Null => JsonVariant::Null,
245                serde_json::Value::Bool(b) => b.into(),
246                serde_json::Value::Number(n) => n.into(),
247                serde_json::Value::String(s) => s.into(),
248                serde_json::Value::Array(array) => {
249                    JsonVariant::Array(array.into_iter().map(helper).collect())
250                }
251                serde_json::Value::Object(object) => {
252                    JsonVariant::Object(object.into_iter().map(|(k, v)| (k, helper(v))).collect())
253                }
254            }
255        }
256        helper(v)
257    }
258}
259
260impl From<BTreeMap<String, JsonVariant>> for JsonVariant {
261    fn from(v: BTreeMap<String, JsonVariant>) -> Self {
262        Self::Object(v)
263    }
264}
265
266impl Display for JsonVariant {
267    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
268        match self {
269            Self::Null => write!(f, "null"),
270            Self::Bool(x) => write!(f, "{x}"),
271            Self::Number(x) => write!(f, "{x}"),
272            Self::String(x) => write!(f, "{x}"),
273            Self::Array(array) => write!(
274                f,
275                "[{}]",
276                array
277                    .iter()
278                    .map(|x| x.to_string())
279                    .collect::<Vec<_>>()
280                    .join(", ")
281            ),
282            Self::Object(object) => {
283                write!(
284                    f,
285                    "{{ {} }}",
286                    object
287                        .iter()
288                        .map(|(k, v)| format!("{k}: {v}"))
289                        .collect::<Vec<_>>()
290                        .join(", ")
291                )
292            }
293            Self::Variant(x) => {
294                let result: serde_json::Result<serde_json::Value> = serde_json::from_slice(x);
295                match result {
296                    Ok(v) => write!(f, "{v}"),
297                    Err(_) => write!(f, "{x:?}"),
298                }
299            }
300        }
301    }
302}
303
304/// Represents any valid JSON value.
305#[derive(Debug, Eq, Serialize, Deserialize)]
306pub struct JsonValue {
307    #[serde(skip)]
308    json_type: OnceLock<JsonType>,
309    json_variant: JsonVariant,
310}
311
312impl JsonValue {
313    pub fn null() -> Self {
314        ().into()
315    }
316
317    pub(crate) fn new(json_variant: JsonVariant) -> Self {
318        Self {
319            json_type: OnceLock::new(),
320            json_variant,
321        }
322    }
323
324    pub(crate) fn data_type(&self) -> ConcreteDataType {
325        ConcreteDataType::Json(self.json_type().clone())
326    }
327
328    pub fn json_type(&self) -> &JsonType {
329        self.json_type.get_or_init(|| self.json_variant.json_type())
330    }
331
332    pub(crate) fn is_null(&self) -> bool {
333        matches!(self.json_variant, JsonVariant::Null)
334    }
335
336    /// Check if this JSON value is an empty object.
337    pub fn is_empty_object(&self) -> bool {
338        match &self.json_variant {
339            JsonVariant::Object(object) => object.is_empty(),
340            _ => false,
341        }
342    }
343
344    pub(crate) fn as_i64(&self) -> Option<i64> {
345        self.json_variant.as_i64()
346    }
347
348    pub(crate) fn as_u64(&self) -> Option<u64> {
349        self.json_variant.as_u64()
350    }
351
352    pub(crate) fn as_f64_lossy(&self) -> Option<f64> {
353        match self.json_variant {
354            JsonVariant::Number(n) => Some(match n {
355                JsonNumber::PosInt(i) => i as f64,
356                JsonNumber::NegInt(i) => i as f64,
357                JsonNumber::Float(f) => f.0,
358            }),
359            _ => None,
360        }
361    }
362
363    pub(crate) fn as_bool(&self) -> Option<bool> {
364        match self.json_variant {
365            JsonVariant::Bool(b) => Some(b),
366            _ => None,
367        }
368    }
369
370    pub fn as_ref(&self) -> JsonValueRef<'_> {
371        JsonValueRef {
372            json_type: OnceLock::new(),
373            json_variant: self.json_variant.as_ref(),
374        }
375    }
376
377    pub fn into_variant(self) -> JsonVariant {
378        self.json_variant
379    }
380
381    pub(crate) fn into_value(self) -> Value {
382        fn helper(v: JsonVariant) -> Value {
383            match v {
384                JsonVariant::Null => Value::Null,
385                JsonVariant::Bool(x) => Value::Boolean(x),
386                JsonVariant::Number(x) => match x {
387                    JsonNumber::PosInt(i) => Value::UInt64(i),
388                    JsonNumber::NegInt(i) => Value::Int64(i),
389                    JsonNumber::Float(f) => Value::Float64(f),
390                },
391                JsonVariant::String(x) => Value::String(x.into()),
392                JsonVariant::Array(array) => {
393                    let values = array.into_iter().map(helper).collect::<Vec<_>>();
394                    debug_assert!(
395                        values
396                            .windows(2)
397                            .all(|w| w[0].data_type() == w[1].data_type())
398                    );
399                    let item_type = values
400                        .first()
401                        .map(|x| x.data_type())
402                        .unwrap_or_else(ConcreteDataType::null_datatype);
403                    Value::List(ListValue::new(values, Arc::new(item_type)))
404                }
405                JsonVariant::Object(object) => {
406                    let mut fields = Vec::with_capacity(object.len());
407                    let mut items = Vec::with_capacity(object.len());
408                    for (k, v) in object {
409                        let v = helper(v);
410                        fields.push(StructField::new(k, v.data_type(), true));
411                        items.push(v);
412                    }
413                    Value::Struct(StructValue::new(items, StructType::new(Arc::new(fields))))
414                }
415                JsonVariant::Variant(x) => Value::Binary(x.into()),
416            }
417        }
418        helper(self.json_variant)
419    }
420
421    /// Recursively aligns this JSON value to `expected` in place. This is to make JSON values fill
422    /// into a [StructArray], which requires a unified static datatype.
423    ///
424    /// Alignment follows these rules:
425    /// - `Null` aligns to any type, and any value aligns to `Null` as `Null`.
426    /// - Numbers are converted only within compatible number categories.
427    /// - Arrays align each element recursively to the expected item type.
428    /// - Objects require `expected` to contain all fields from the current value. Missing expected
429    ///   fields are filled with `Null`.
430    /// - `Variant` preserves the original JSON payload as serialized bytes.
431    ///
432    /// Returns an error if the value cannot be aligned without losing existing object fields or
433    /// when a scalar type conversion is incompatible.
434    pub(crate) fn try_align(&mut self, expected: &JsonType) -> Result<()> {
435        if self.json_type() == expected {
436            return Ok(());
437        }
438
439        fn helper(value: JsonVariant, expected: &JsonNativeType) -> Result<JsonVariant> {
440            Ok(match (value, expected) {
441                (JsonVariant::Null, _) | (_, JsonNativeType::Null) => JsonVariant::Null,
442                (JsonVariant::Bool(v), JsonNativeType::Bool) => JsonVariant::Bool(v),
443                (JsonVariant::Number(v), JsonNativeType::Number(n)) => {
444                    return match n {
445                        JsonNumberType::U64 => v
446                            .as_u64()
447                            .map(|x| JsonVariant::Number(JsonNumber::PosInt(x))),
448                        JsonNumberType::I64 => v
449                            .as_i64()
450                            .map(|x| JsonVariant::Number(JsonNumber::NegInt(x))),
451                        JsonNumberType::F64 => {
452                            Some(JsonVariant::Number(JsonNumber::Float(v.as_f64().into())))
453                        }
454                    }
455                    .with_context(|| AlignJsonValueSnafu {
456                        reason: format!("unable to align number ‘{}’ to type {}", v, expected),
457                    });
458                }
459                (JsonVariant::String(v), JsonNativeType::String) => JsonVariant::String(v),
460
461                (JsonVariant::Array(items), JsonNativeType::Array(expected)) => JsonVariant::Array(
462                    items
463                        .into_iter()
464                        .map(|item| helper(item, expected.as_ref()))
465                        .collect::<Result<_>>()?,
466                ),
467
468                (JsonVariant::Object(kvs), _) if kvs.is_empty() => JsonVariant::Null,
469                (JsonVariant::Object(mut kvs), JsonNativeType::Object(expected)) => {
470                    ensure!(
471                        expected.keys().len() >= kvs.keys().len()
472                            && kvs.keys().all(|k| expected.contains_key(k)),
473                        AlignJsonValueSnafu {
474                            reason: format!(
475                                "aligned type '{}' should be superset of value '{}'",
476                                JsonNativeType::Object(expected.clone()),
477                                JsonVariant::from(kvs),
478                            )
479                        }
480                    );
481
482                    let mut object = BTreeMap::new();
483                    for (field, field_type) in expected {
484                        if let Some((k, v)) = kvs.remove_entry(field) {
485                            object.insert(k, helper(v, field_type)?);
486                        } else {
487                            object.insert(field.clone(), JsonVariant::Null);
488                        }
489                    }
490                    JsonVariant::Object(object)
491                }
492
493                (v, JsonNativeType::Variant) => {
494                    let json: serde_json::Value =
495                        JsonValue::new(v).try_into().context(SerializeSnafu)?;
496                    serde_json::to_vec(&json)
497                        .map(JsonVariant::Variant)
498                        .context(SerializeSnafu)?
499                }
500
501                (value, expected) => {
502                    return AlignJsonValueSnafu {
503                        reason: format!(
504                            "unable to align '{}' of type {} to type {}",
505                            value,
506                            value.native_type(),
507                            expected,
508                        ),
509                    }
510                    .fail();
511                }
512            })
513        }
514
515        let x = std::mem::take(&mut self.json_variant);
516        self.json_variant = helper(x, expected.native_type())?;
517        self.json_type = OnceLock::new();
518        Ok(())
519    }
520}
521
522impl<T: Into<JsonVariant>> From<T> for JsonValue {
523    fn from(v: T) -> Self {
524        Self {
525            json_type: OnceLock::new(),
526            json_variant: v.into(),
527        }
528    }
529}
530
531impl TryFrom<JsonValue> for serde_json::Value {
532    type Error = serde_json::Error;
533
534    fn try_from(v: JsonValue) -> serde_json::Result<Self> {
535        fn helper(v: JsonVariant) -> serde_json::Result<serde_json::Value> {
536            Ok(match v {
537                JsonVariant::Null => serde_json::Value::Null,
538                JsonVariant::Bool(x) => serde_json::Value::Bool(x),
539                JsonVariant::Number(x) => match x {
540                    JsonNumber::PosInt(i) => serde_json::Value::Number(i.into()),
541                    JsonNumber::NegInt(i) => serde_json::Value::Number(i.into()),
542                    JsonNumber::Float(f) => {
543                        if let Some(x) = Number::from_f64(f.0) {
544                            serde_json::Value::Number(x)
545                        } else {
546                            serde_json::Value::String("NaN".into())
547                        }
548                    }
549                },
550                JsonVariant::String(x) => serde_json::Value::String(x),
551                JsonVariant::Array(array) => serde_json::Value::Array(
552                    array
553                        .into_iter()
554                        .map(helper)
555                        .collect::<serde_json::Result<Vec<_>>>()?,
556                ),
557                JsonVariant::Object(object) => {
558                    let mut map = serde_json::Map::with_capacity(object.len());
559                    for (k, v) in object {
560                        map.insert(k, helper(v)?);
561                    }
562                    serde_json::Value::Object(map)
563                }
564                JsonVariant::Variant(x) => serde_json::from_slice(&x)?,
565            })
566        }
567        helper(v.json_variant)
568    }
569}
570
571impl Clone for JsonValue {
572    fn clone(&self) -> Self {
573        let Self {
574            json_type: _,
575            json_variant,
576        } = self;
577        Self {
578            json_type: OnceLock::new(),
579            json_variant: json_variant.clone(),
580        }
581    }
582}
583
584impl PartialEq<JsonValue> for JsonValue {
585    fn eq(&self, other: &JsonValue) -> bool {
586        let Self {
587            json_type: _,
588            json_variant,
589        } = self;
590        json_variant.eq(&other.json_variant)
591    }
592}
593
594impl Hash for JsonValue {
595    fn hash<H: Hasher>(&self, state: &mut H) {
596        let Self {
597            json_type: _,
598            json_variant,
599        } = self;
600        json_variant.hash(state);
601    }
602}
603
604impl Display for JsonValue {
605    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
606        write!(f, "{}", self.json_variant)
607    }
608}
609
610/// References of variants of json.
611#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
612pub enum JsonVariantRef<'a> {
613    Null,
614    Bool(bool),
615    Number(JsonNumber),
616    String(&'a str),
617    Array(Vec<JsonVariantRef<'a>>),
618    Object(BTreeMap<&'a str, JsonVariantRef<'a>>),
619    Variant(&'a [u8]),
620}
621
622impl JsonVariantRef<'_> {
623    fn native_type(&self) -> JsonNativeType {
624        match self {
625            JsonVariantRef::Null => JsonNativeType::Null,
626            JsonVariantRef::Bool(_) => JsonNativeType::Bool,
627            JsonVariantRef::Number(n) => n.native_type(),
628            JsonVariantRef::String(_) => JsonNativeType::String,
629            JsonVariantRef::Array(array) => {
630                json_array_native_type(array.iter().map(JsonVariantRef::native_type))
631            }
632            JsonVariantRef::Object(object) => {
633                json_object_native_type(object.iter().map(|(k, v)| (*k, v.native_type())))
634            }
635            JsonVariantRef::Variant(_) => JsonNativeType::Variant,
636        }
637    }
638
639    fn json_type(&self) -> JsonType {
640        JsonType::new_json2(self.native_type())
641    }
642}
643
644fn json_array_native_type<I>(items: I) -> JsonNativeType
645where
646    I: IntoIterator<Item = JsonNativeType>,
647{
648    let mut iter = items.into_iter();
649    let mut item_type = match iter.next() {
650        Some(t) => t,
651        None => return JsonNativeType::Array(Box::new(JsonNativeType::Null)),
652    };
653    for x in iter {
654        if matches!(item_type, JsonNativeType::Variant) {
655            break;
656        }
657        item_type.merge(&x);
658    }
659    JsonNativeType::Array(Box::new(item_type))
660}
661
662fn json_object_native_type<I, K>(fields: I) -> JsonNativeType
663where
664    I: IntoIterator<Item = (K, JsonNativeType)>,
665    K: Into<String>,
666{
667    let mut fields = fields.into_iter().peekable();
668    if fields.peek().is_none() {
669        JsonNativeType::Null
670    } else {
671        JsonNativeType::Object(fields.map(|(k, v)| (k.into(), v)).collect())
672    }
673}
674
675impl From<()> for JsonVariantRef<'_> {
676    fn from(_: ()) -> Self {
677        Self::Null
678    }
679}
680
681impl From<bool> for JsonVariantRef<'_> {
682    fn from(v: bool) -> Self {
683        Self::Bool(v)
684    }
685}
686
687impl<T: Into<JsonNumber>> From<T> for JsonVariantRef<'_> {
688    fn from(v: T) -> Self {
689        Self::Number(v.into())
690    }
691}
692
693impl<'a> From<&'a str> for JsonVariantRef<'a> {
694    fn from(v: &'a str) -> Self {
695        Self::String(v)
696    }
697}
698
699impl<'a, const N: usize, T: Into<JsonVariantRef<'a>>> From<[T; N]> for JsonVariantRef<'a> {
700    fn from(vs: [T; N]) -> Self {
701        Self::Array(vs.into_iter().map(|x| x.into()).collect())
702    }
703}
704
705impl<'a, V: Into<JsonVariantRef<'a>>, const N: usize> From<[(&'a str, V); N]>
706    for JsonVariantRef<'a>
707{
708    fn from(vs: [(&'a str, V); N]) -> Self {
709        Self::Object(vs.into_iter().map(|(k, v)| (k, v.into())).collect())
710    }
711}
712
713impl<'a> From<Vec<JsonVariantRef<'a>>> for JsonVariantRef<'a> {
714    fn from(v: Vec<JsonVariantRef<'a>>) -> Self {
715        Self::Array(v)
716    }
717}
718
719impl<'a> From<BTreeMap<&'a str, JsonVariantRef<'a>>> for JsonVariantRef<'a> {
720    fn from(v: BTreeMap<&'a str, JsonVariantRef<'a>>) -> Self {
721        Self::Object(v)
722    }
723}
724
725impl From<JsonVariantRef<'_>> for JsonVariant {
726    fn from(v: JsonVariantRef) -> Self {
727        match v {
728            JsonVariantRef::Null => Self::Null,
729            JsonVariantRef::Bool(x) => Self::Bool(x),
730            JsonVariantRef::Number(x) => Self::Number(x),
731            JsonVariantRef::String(x) => Self::String(x.to_string()),
732            JsonVariantRef::Array(array) => {
733                Self::Array(array.into_iter().map(Into::into).collect())
734            }
735            JsonVariantRef::Object(object) => Self::Object(
736                object
737                    .into_iter()
738                    .map(|(k, v)| (k.to_string(), v.into()))
739                    .collect(),
740            ),
741            JsonVariantRef::Variant(x) => Self::Variant(x.to_vec()),
742        }
743    }
744}
745
746impl<'a> From<&'a [u8]> for JsonVariantRef<'a> {
747    fn from(value: &'a [u8]) -> Self {
748        Self::Variant(value)
749    }
750}
751
752/// Reference to representation of any valid JSON value.
753#[derive(Debug, Serialize)]
754pub struct JsonValueRef<'a> {
755    #[serde(skip)]
756    json_type: OnceLock<JsonType>,
757    json_variant: JsonVariantRef<'a>,
758}
759
760impl<'a> JsonValueRef<'a> {
761    pub fn null() -> Self {
762        ().into()
763    }
764
765    pub(crate) fn data_type(&self) -> ConcreteDataType {
766        ConcreteDataType::Json(self.json_type().clone())
767    }
768
769    pub(crate) fn json_type(&self) -> &JsonType {
770        self.json_type.get_or_init(|| self.json_variant.json_type())
771    }
772
773    pub fn into_variant(self) -> JsonVariantRef<'a> {
774        self.json_variant
775    }
776
777    pub(crate) fn is_null(&self) -> bool {
778        matches!(self.json_variant, JsonVariantRef::Null)
779    }
780
781    pub fn is_object(&self) -> bool {
782        matches!(self.json_variant, JsonVariantRef::Object(_))
783    }
784
785    pub(crate) fn as_f32(&self) -> Option<f32> {
786        match self.json_variant {
787            JsonVariantRef::Number(JsonNumber::Float(f)) => f.to_f32(),
788            _ => None,
789        }
790    }
791
792    pub(crate) fn as_f64(&self) -> Option<f64> {
793        match self.json_variant {
794            JsonVariantRef::Number(JsonNumber::Float(f)) => Some(f.0),
795            _ => None,
796        }
797    }
798
799    fn as_value_ref(&self) -> ValueRef<'_> {
800        fn helper<'a>(v: &'a JsonVariantRef) -> ValueRef<'a> {
801            match v {
802                JsonVariantRef::Null => ValueRef::Null,
803                JsonVariantRef::Bool(x) => ValueRef::Boolean(*x),
804                JsonVariantRef::Number(x) => match x {
805                    JsonNumber::PosInt(i) => ValueRef::UInt64(*i),
806                    JsonNumber::NegInt(i) => ValueRef::Int64(*i),
807                    JsonNumber::Float(f) => ValueRef::Float64(*f),
808                },
809                JsonVariantRef::String(x) => ValueRef::String(x),
810                JsonVariantRef::Array(array) => {
811                    let val = array.iter().map(helper).collect::<Vec<_>>();
812                    let item_datatype = if let Some(first) = val.first() {
813                        first.data_type()
814                    } else {
815                        ConcreteDataType::null_datatype()
816                    };
817                    ValueRef::List(ListValueRef::RefList {
818                        val,
819                        item_datatype: Arc::new(item_datatype),
820                    })
821                }
822                JsonVariantRef::Object(object) => {
823                    let mut fields = Vec::with_capacity(object.len());
824                    let mut val = Vec::with_capacity(object.len());
825                    for (k, v) in object.iter() {
826                        let v = helper(v);
827                        fields.push(StructField::new(k.to_string(), v.data_type(), true));
828                        val.push(v);
829                    }
830                    ValueRef::Struct(StructValueRef::RefList {
831                        val,
832                        fields: StructType::new(Arc::new(fields)),
833                    })
834                }
835                JsonVariantRef::Variant(x) => ValueRef::Binary(x),
836            }
837        }
838        helper(&self.json_variant)
839    }
840
841    pub(crate) fn data_size(&self) -> usize {
842        size_of_val(self)
843    }
844
845    pub(crate) fn variant(&self) -> &JsonVariantRef<'a> {
846        &self.json_variant
847    }
848
849    pub(crate) fn as_struct_value(&self) -> ValueRef<'_> {
850        if self.is_object() {
851            return self.as_value_ref();
852        }
853
854        ValueRef::Struct(StructValueRef::RefList {
855            val: vec![self.as_value_ref()],
856            fields: self.json_type().as_struct_type(),
857        })
858    }
859}
860
861impl<'a, T: Into<JsonVariantRef<'a>>> From<T> for JsonValueRef<'a> {
862    fn from(v: T) -> Self {
863        Self {
864            json_type: OnceLock::new(),
865            json_variant: v.into(),
866        }
867    }
868}
869
870impl From<JsonValueRef<'_>> for JsonValue {
871    fn from(v: JsonValueRef<'_>) -> Self {
872        Self {
873            json_type: OnceLock::new(),
874            json_variant: v.json_variant.into(),
875        }
876    }
877}
878
879impl PartialEq for JsonValueRef<'_> {
880    fn eq(&self, other: &Self) -> bool {
881        let Self {
882            json_type: _,
883            json_variant,
884        } = self;
885        json_variant == &other.json_variant
886    }
887}
888
889impl Eq for JsonValueRef<'_> {}
890
891impl Clone for JsonValueRef<'_> {
892    fn clone(&self) -> Self {
893        let Self {
894            json_type: _,
895            json_variant,
896        } = self;
897        Self {
898            json_type: OnceLock::new(),
899            json_variant: json_variant.clone(),
900        }
901    }
902}
903
904#[cfg(test)]
905mod tests {
906    use super::*;
907    use crate::types::json_type::JsonObjectType;
908
909    #[test]
910    fn test_align_json_value() -> Result<()> {
911        fn parse_json_value(json: &str) -> JsonValue {
912            let value: serde_json::Value = serde_json::from_str(json).unwrap();
913            value.into()
914        }
915
916        // Root type can be aligned to Null, and the cached json_type must be refreshed.
917        let mut value = JsonValue::from(true);
918        assert_eq!(
919            value.json_type(),
920            &JsonType::new_json2(JsonNativeType::Bool)
921        );
922        value.try_align(&JsonType::null())?;
923        assert_eq!(value, JsonValue::null());
924        assert_eq!(value.json_type(), &JsonType::null());
925
926        // Object alignment now requires the expected type to be a superset of the
927        // value fields, while still filling missing expected fields with null.
928        let expected = JsonType::new_json2(JsonNativeType::Object(JsonObjectType::from([
929            ("extra".to_string(), JsonNativeType::u64()),
930            (
931                "items".to_string(),
932                JsonNativeType::Array(Box::new(JsonNativeType::Object(JsonObjectType::from([
933                    ("id".to_string(), JsonNativeType::u64()),
934                    ("payload".to_string(), JsonNativeType::Variant),
935                    ("note".to_string(), JsonNativeType::String),
936                ])))),
937            ),
938            ("name".to_string(), JsonNativeType::String),
939        ])));
940        let mut value = parse_json_value(r#"{"items":[{"id":1,"payload":{"k":"v"}}],"extra":1}"#);
941        assert_ne!(value.json_type(), &expected);
942        value.try_align(&expected)?;
943        assert_eq!(
944            value,
945            JsonValue::from(JsonVariant::Object(BTreeMap::from([
946                ("extra".to_string(), JsonVariant::from(1_u64)),
947                (
948                    "items".to_string(),
949                    JsonVariant::Array(vec![JsonVariant::Object(BTreeMap::from([
950                        ("id".to_string(), JsonVariant::from(1_u64)),
951                        ("note".to_string(), JsonVariant::Null),
952                        (
953                            "payload".to_string(),
954                            JsonVariant::Variant(br#"{"k":"v"}"#.to_vec()),
955                        ),
956                    ]))]),
957                ),
958                ("name".to_string(), JsonVariant::Null),
959            ])))
960        );
961
962        // Object alignment should fail if the expected type misses any field from the value.
963        let expected = JsonType::new_json2(JsonNativeType::Object(JsonObjectType::from([(
964            "items".to_string(),
965            JsonNativeType::Array(Box::new(JsonNativeType::Object(JsonObjectType::from([
966                ("id".to_string(), JsonNativeType::u64()),
967                ("payload".to_string(), JsonNativeType::Variant),
968            ])))),
969        )])));
970        let mut value =
971            parse_json_value(r#"{"items":[{"id":1,"payload":{"k":"v"},"extra":true}]}"#);
972        let err = value.try_align(&expected).unwrap_err();
973        assert_eq!(
974            err.to_string(),
975            r#"Failed to align JSON value, reason: aligned type '{"id":"<Number>","payload":"<Variant>"}' should be superset of value '{ extra: true, id: 1, payload: { k: v } }'"#
976        );
977
978        // Root-level Variant alignment should preserve the original JSON payload.
979        let mut value = parse_json_value(r#"{"foo":[1,true,null]}"#);
980        value.try_align(&JsonType::new_json2(JsonNativeType::Variant))?;
981        assert_eq!(
982            value,
983            JsonValue::from(JsonVariant::Variant(br#"{"foo":[1,true,null]}"#.to_vec()))
984        );
985
986        // Incompatible scalar alignment should fail instead of coercing the value.
987        let mut value = JsonValue::from("hello");
988        let err = value
989            .try_align(&JsonType::new_json2(JsonNativeType::Bool))
990            .unwrap_err();
991        assert_eq!(
992            err.to_string(),
993            r#"Failed to align JSON value, reason: unable to align 'hello' of type "<String>" to type "<Bool>""#
994        );
995
996        Ok(())
997    }
998}