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
70impl From<u64> for JsonNumber {
71    fn from(i: u64) -> Self {
72        Self::PosInt(i)
73    }
74}
75
76impl From<i64> for JsonNumber {
77    fn from(n: i64) -> Self {
78        Self::NegInt(n)
79    }
80}
81
82impl From<f64> for JsonNumber {
83    fn from(i: f64) -> Self {
84        Self::Float(i.into())
85    }
86}
87
88impl From<Number> for JsonNumber {
89    fn from(n: Number) -> Self {
90        if let Some(i) = n.as_i64() {
91            i.into()
92        } else if let Some(i) = n.as_u64() {
93            i.into()
94        } else {
95            n.as_f64().unwrap_or(f64::NAN).into()
96        }
97    }
98}
99
100impl Display for JsonNumber {
101    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102        match self {
103            Self::PosInt(x) => write!(f, "{x}"),
104            Self::NegInt(x) => write!(f, "{x}"),
105            Self::Float(x) => write!(f, "{x}"),
106        }
107    }
108}
109
110/// Variants of json.
111#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
112pub enum JsonVariant {
113    #[default]
114    Null,
115    Bool(bool),
116    Number(JsonNumber),
117    String(String),
118    Array(Vec<JsonVariant>),
119    Object(BTreeMap<String, JsonVariant>),
120    /// A special "variant" value of JSON, to represent a union result of conflict JSON type values.
121    Variant(Vec<u8>),
122}
123
124impl JsonVariant {
125    pub(crate) fn as_i64(&self) -> Option<i64> {
126        match self {
127            JsonVariant::Number(n) => n.as_i64(),
128            _ => None,
129        }
130    }
131
132    pub(crate) fn as_u64(&self) -> Option<u64> {
133        match self {
134            JsonVariant::Number(n) => n.as_u64(),
135            _ => None,
136        }
137    }
138
139    pub(crate) fn as_f64(&self) -> Option<f64> {
140        match self {
141            JsonVariant::Number(n) => Some(n.as_f64()),
142            _ => None,
143        }
144    }
145
146    pub(crate) fn native_type(&self) -> JsonNativeType {
147        match self {
148            JsonVariant::Null => JsonNativeType::Null,
149            JsonVariant::Bool(_) => JsonNativeType::Bool,
150            JsonVariant::Number(n) => match n {
151                JsonNumber::PosInt(_) => JsonNativeType::u64(),
152                JsonNumber::NegInt(_) => JsonNativeType::i64(),
153                JsonNumber::Float(_) => JsonNativeType::f64(),
154            },
155            JsonVariant::String(_) => JsonNativeType::String,
156            JsonVariant::Array(array) => {
157                let item_type = if let Some(first) = array.first() {
158                    first.native_type()
159                } else {
160                    JsonNativeType::Null
161                };
162                JsonNativeType::Array(Box::new(item_type))
163            }
164            JsonVariant::Object(object) => JsonNativeType::Object(
165                object
166                    .iter()
167                    .map(|(k, v)| (k.clone(), v.native_type()))
168                    .collect(),
169            ),
170            JsonVariant::Variant(_) => JsonNativeType::Variant,
171        }
172    }
173
174    fn json_type(&self) -> JsonType {
175        JsonType::new_json2(self.native_type())
176    }
177
178    fn as_ref(&self) -> JsonVariantRef<'_> {
179        match self {
180            JsonVariant::Null => JsonVariantRef::Null,
181            JsonVariant::Bool(x) => (*x).into(),
182            JsonVariant::Number(x) => match x {
183                JsonNumber::PosInt(i) => (*i).into(),
184                JsonNumber::NegInt(i) => (*i).into(),
185                JsonNumber::Float(f) => (f.0).into(),
186            },
187            JsonVariant::String(x) => x.as_str().into(),
188            JsonVariant::Array(array) => {
189                JsonVariantRef::Array(array.iter().map(|x| x.as_ref()).collect())
190            }
191            JsonVariant::Object(object) => JsonVariantRef::Object(
192                object
193                    .iter()
194                    .map(|(k, v)| (k.as_str(), v.as_ref()))
195                    .collect(),
196            ),
197            JsonVariant::Variant(v) => JsonVariantRef::Variant(v),
198        }
199    }
200}
201
202impl From<()> for JsonVariant {
203    fn from(_: ()) -> Self {
204        Self::Null
205    }
206}
207
208impl From<bool> for JsonVariant {
209    fn from(v: bool) -> Self {
210        Self::Bool(v)
211    }
212}
213
214impl<T: Into<JsonNumber>> From<T> for JsonVariant {
215    fn from(v: T) -> Self {
216        Self::Number(v.into())
217    }
218}
219
220impl From<&str> for JsonVariant {
221    fn from(v: &str) -> Self {
222        Self::String(v.to_string())
223    }
224}
225
226impl From<String> for JsonVariant {
227    fn from(v: String) -> Self {
228        Self::String(v)
229    }
230}
231
232impl<const N: usize, T: Into<JsonVariant>> From<[T; N]> for JsonVariant {
233    fn from(vs: [T; N]) -> Self {
234        Self::Array(vs.into_iter().map(|x| x.into()).collect())
235    }
236}
237
238impl<K: Into<String>, V: Into<JsonVariant>, const N: usize> From<[(K, V); N]> for JsonVariant {
239    fn from(vs: [(K, V); N]) -> Self {
240        Self::Object(vs.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
241    }
242}
243
244impl From<serde_json::Value> for JsonVariant {
245    fn from(v: serde_json::Value) -> Self {
246        fn helper(v: serde_json::Value) -> JsonVariant {
247            match v {
248                serde_json::Value::Null => JsonVariant::Null,
249                serde_json::Value::Bool(b) => b.into(),
250                serde_json::Value::Number(n) => n.into(),
251                serde_json::Value::String(s) => s.into(),
252                serde_json::Value::Array(array) => {
253                    JsonVariant::Array(array.into_iter().map(helper).collect())
254                }
255                serde_json::Value::Object(object) => {
256                    JsonVariant::Object(object.into_iter().map(|(k, v)| (k, helper(v))).collect())
257                }
258            }
259        }
260        helper(v)
261    }
262}
263
264impl From<BTreeMap<String, JsonVariant>> for JsonVariant {
265    fn from(v: BTreeMap<String, JsonVariant>) -> Self {
266        Self::Object(v)
267    }
268}
269
270impl Display for JsonVariant {
271    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
272        match self {
273            Self::Null => write!(f, "null"),
274            Self::Bool(x) => write!(f, "{x}"),
275            Self::Number(x) => write!(f, "{x}"),
276            Self::String(x) => write!(f, "{x}"),
277            Self::Array(array) => write!(
278                f,
279                "[{}]",
280                array
281                    .iter()
282                    .map(|x| x.to_string())
283                    .collect::<Vec<_>>()
284                    .join(", ")
285            ),
286            Self::Object(object) => {
287                write!(
288                    f,
289                    "{{ {} }}",
290                    object
291                        .iter()
292                        .map(|(k, v)| format!("{k}: {v}"))
293                        .collect::<Vec<_>>()
294                        .join(", ")
295                )
296            }
297            Self::Variant(x) => {
298                let result: serde_json::Result<serde_json::Value> = serde_json::from_slice(x);
299                match result {
300                    Ok(v) => write!(f, "{v}"),
301                    Err(_) => write!(f, "{x:?}"),
302                }
303            }
304        }
305    }
306}
307
308/// Represents any valid JSON value.
309#[derive(Debug, Eq, Serialize, Deserialize)]
310pub struct JsonValue {
311    #[serde(skip)]
312    json_type: OnceLock<JsonType>,
313    json_variant: JsonVariant,
314}
315
316impl JsonValue {
317    pub fn null() -> Self {
318        ().into()
319    }
320
321    pub(crate) fn new(json_variant: JsonVariant) -> Self {
322        Self {
323            json_type: OnceLock::new(),
324            json_variant,
325        }
326    }
327
328    pub(crate) fn data_type(&self) -> ConcreteDataType {
329        ConcreteDataType::Json(self.json_type().clone())
330    }
331
332    pub fn json_type(&self) -> &JsonType {
333        self.json_type.get_or_init(|| self.json_variant.json_type())
334    }
335
336    pub(crate) fn is_null(&self) -> bool {
337        matches!(self.json_variant, JsonVariant::Null)
338    }
339
340    /// Check if this JSON value is an empty object.
341    pub fn is_empty_object(&self) -> bool {
342        match &self.json_variant {
343            JsonVariant::Object(object) => object.is_empty(),
344            _ => false,
345        }
346    }
347
348    pub(crate) fn as_i64(&self) -> Option<i64> {
349        self.json_variant.as_i64()
350    }
351
352    pub(crate) fn as_u64(&self) -> Option<u64> {
353        self.json_variant.as_u64()
354    }
355
356    pub(crate) fn as_f64_lossy(&self) -> Option<f64> {
357        match self.json_variant {
358            JsonVariant::Number(n) => Some(match n {
359                JsonNumber::PosInt(i) => i as f64,
360                JsonNumber::NegInt(i) => i as f64,
361                JsonNumber::Float(f) => f.0,
362            }),
363            _ => None,
364        }
365    }
366
367    pub(crate) fn as_bool(&self) -> Option<bool> {
368        match self.json_variant {
369            JsonVariant::Bool(b) => Some(b),
370            _ => None,
371        }
372    }
373
374    pub fn as_ref(&self) -> JsonValueRef<'_> {
375        JsonValueRef {
376            json_type: OnceLock::new(),
377            json_variant: self.json_variant.as_ref(),
378        }
379    }
380
381    pub fn into_variant(self) -> JsonVariant {
382        self.json_variant
383    }
384
385    pub(crate) fn into_value(self) -> Value {
386        fn helper(v: JsonVariant) -> Value {
387            match v {
388                JsonVariant::Null => Value::Null,
389                JsonVariant::Bool(x) => Value::Boolean(x),
390                JsonVariant::Number(x) => match x {
391                    JsonNumber::PosInt(i) => Value::UInt64(i),
392                    JsonNumber::NegInt(i) => Value::Int64(i),
393                    JsonNumber::Float(f) => Value::Float64(f),
394                },
395                JsonVariant::String(x) => Value::String(x.into()),
396                JsonVariant::Array(array) => {
397                    let item_type = if let Some(first) = array.first() {
398                        first.native_type()
399                    } else {
400                        JsonNativeType::Null
401                    };
402                    Value::List(ListValue::new(
403                        array.into_iter().map(helper).collect(),
404                        Arc::new((&item_type).into()),
405                    ))
406                }
407                JsonVariant::Object(object) => {
408                    let mut fields = Vec::with_capacity(object.len());
409                    let mut items = Vec::with_capacity(object.len());
410                    for (k, v) in object {
411                        fields.push(StructField::new(k, (&v.native_type()).into(), true));
412                        items.push(helper(v));
413                    }
414                    Value::Struct(StructValue::new(items, StructType::new(Arc::new(fields))))
415                }
416                JsonVariant::Variant(x) => Value::Binary(x.into()),
417            }
418        }
419        helper(self.json_variant)
420    }
421
422    /// Recursively aligns this JSON value to `expected` in place. This is to make JSON values fill
423    /// into a [StructArray], which requires a unified static datatype.
424    ///
425    /// Alignment follows these rules:
426    /// - `Null` aligns to any type, and any value aligns to `Null` as `Null`.
427    /// - Numbers are converted only within compatible number categories.
428    /// - Arrays align each element recursively to the expected item type.
429    /// - Objects require `expected` to contain all fields from the current value. Missing expected
430    ///   fields are filled with `Null`.
431    /// - `Variant` preserves the original JSON payload as serialized bytes.
432    ///
433    /// Returns an error if the value cannot be aligned without losing existing object fields or
434    /// when a scalar type conversion is incompatible.
435    pub(crate) fn try_align(&mut self, expected: &JsonType) -> Result<()> {
436        if self.json_type() == expected {
437            return Ok(());
438        }
439
440        fn helper(value: JsonVariant, expected: &JsonNativeType) -> Result<JsonVariant> {
441            Ok(match (value, expected) {
442                (JsonVariant::Null, _) | (_, JsonNativeType::Null) => JsonVariant::Null,
443                (JsonVariant::Bool(v), JsonNativeType::Bool) => JsonVariant::Bool(v),
444                (JsonVariant::Number(v), JsonNativeType::Number(n)) => {
445                    return match n {
446                        JsonNumberType::U64 => v
447                            .as_u64()
448                            .map(|x| JsonVariant::Number(JsonNumber::PosInt(x))),
449                        JsonNumberType::I64 => v
450                            .as_i64()
451                            .map(|x| JsonVariant::Number(JsonNumber::NegInt(x))),
452                        JsonNumberType::F64 => {
453                            Some(JsonVariant::Number(JsonNumber::Float(v.as_f64().into())))
454                        }
455                    }
456                    .with_context(|| AlignJsonValueSnafu {
457                        reason: format!("unable to align number ‘{}’ to type {}", v, expected),
458                    });
459                }
460                (JsonVariant::String(v), JsonNativeType::String) => JsonVariant::String(v),
461
462                (JsonVariant::Array(items), JsonNativeType::Array(expected)) => JsonVariant::Array(
463                    items
464                        .into_iter()
465                        .map(|item| helper(item, expected.as_ref()))
466                        .collect::<Result<_>>()?,
467                ),
468
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::from(expected.clone());
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 json_type(&self) -> JsonType {
624        fn native_type(v: &JsonVariantRef<'_>) -> JsonNativeType {
625            match v {
626                JsonVariantRef::Null => JsonNativeType::Null,
627                JsonVariantRef::Bool(_) => JsonNativeType::Bool,
628                JsonVariantRef::Number(n) => match n {
629                    JsonNumber::PosInt(_) => JsonNativeType::u64(),
630                    JsonNumber::NegInt(_) => JsonNativeType::i64(),
631                    JsonNumber::Float(_) => JsonNativeType::f64(),
632                },
633                JsonVariantRef::String(_) => JsonNativeType::String,
634                JsonVariantRef::Array(array) => {
635                    let item_type = if let Some(first) = array.first() {
636                        native_type(first)
637                    } else {
638                        JsonNativeType::Null
639                    };
640                    JsonNativeType::Array(Box::new(item_type))
641                }
642                JsonVariantRef::Object(object) => JsonNativeType::Object(
643                    object
644                        .iter()
645                        .map(|(k, v)| (k.to_string(), native_type(v)))
646                        .collect(),
647                ),
648                JsonVariantRef::Variant(_) => JsonNativeType::Variant,
649            }
650        }
651        JsonType::new_json2(native_type(self))
652    }
653}
654
655impl From<()> for JsonVariantRef<'_> {
656    fn from(_: ()) -> Self {
657        Self::Null
658    }
659}
660
661impl From<bool> for JsonVariantRef<'_> {
662    fn from(v: bool) -> Self {
663        Self::Bool(v)
664    }
665}
666
667impl<T: Into<JsonNumber>> From<T> for JsonVariantRef<'_> {
668    fn from(v: T) -> Self {
669        Self::Number(v.into())
670    }
671}
672
673impl<'a> From<&'a str> for JsonVariantRef<'a> {
674    fn from(v: &'a str) -> Self {
675        Self::String(v)
676    }
677}
678
679impl<'a, const N: usize, T: Into<JsonVariantRef<'a>>> From<[T; N]> for JsonVariantRef<'a> {
680    fn from(vs: [T; N]) -> Self {
681        Self::Array(vs.into_iter().map(|x| x.into()).collect())
682    }
683}
684
685impl<'a, V: Into<JsonVariantRef<'a>>, const N: usize> From<[(&'a str, V); N]>
686    for JsonVariantRef<'a>
687{
688    fn from(vs: [(&'a str, V); N]) -> Self {
689        Self::Object(vs.into_iter().map(|(k, v)| (k, v.into())).collect())
690    }
691}
692
693impl<'a> From<Vec<JsonVariantRef<'a>>> for JsonVariantRef<'a> {
694    fn from(v: Vec<JsonVariantRef<'a>>) -> Self {
695        Self::Array(v)
696    }
697}
698
699impl<'a> From<BTreeMap<&'a str, JsonVariantRef<'a>>> for JsonVariantRef<'a> {
700    fn from(v: BTreeMap<&'a str, JsonVariantRef<'a>>) -> Self {
701        Self::Object(v)
702    }
703}
704
705impl From<JsonVariantRef<'_>> for JsonVariant {
706    fn from(v: JsonVariantRef) -> Self {
707        match v {
708            JsonVariantRef::Null => Self::Null,
709            JsonVariantRef::Bool(x) => Self::Bool(x),
710            JsonVariantRef::Number(x) => Self::Number(x),
711            JsonVariantRef::String(x) => Self::String(x.to_string()),
712            JsonVariantRef::Array(array) => {
713                Self::Array(array.into_iter().map(Into::into).collect())
714            }
715            JsonVariantRef::Object(object) => Self::Object(
716                object
717                    .into_iter()
718                    .map(|(k, v)| (k.to_string(), v.into()))
719                    .collect(),
720            ),
721            JsonVariantRef::Variant(x) => Self::Variant(x.to_vec()),
722        }
723    }
724}
725
726impl<'a> From<&'a [u8]> for JsonVariantRef<'a> {
727    fn from(value: &'a [u8]) -> Self {
728        Self::Variant(value)
729    }
730}
731
732/// Reference to representation of any valid JSON value.
733#[derive(Debug, Serialize)]
734pub struct JsonValueRef<'a> {
735    #[serde(skip)]
736    json_type: OnceLock<JsonType>,
737    json_variant: JsonVariantRef<'a>,
738}
739
740impl<'a> JsonValueRef<'a> {
741    pub fn null() -> Self {
742        ().into()
743    }
744
745    pub(crate) fn data_type(&self) -> ConcreteDataType {
746        ConcreteDataType::Json(self.json_type().clone())
747    }
748
749    pub(crate) fn json_type(&self) -> &JsonType {
750        self.json_type.get_or_init(|| self.json_variant.json_type())
751    }
752
753    pub fn into_variant(self) -> JsonVariantRef<'a> {
754        self.json_variant
755    }
756
757    pub(crate) fn is_null(&self) -> bool {
758        matches!(self.json_variant, JsonVariantRef::Null)
759    }
760
761    pub fn is_object(&self) -> bool {
762        matches!(self.json_variant, JsonVariantRef::Object(_))
763    }
764
765    pub(crate) fn as_f32(&self) -> Option<f32> {
766        match self.json_variant {
767            JsonVariantRef::Number(JsonNumber::Float(f)) => f.to_f32(),
768            _ => None,
769        }
770    }
771
772    pub(crate) fn as_f64(&self) -> Option<f64> {
773        match self.json_variant {
774            JsonVariantRef::Number(JsonNumber::Float(f)) => Some(f.0),
775            _ => None,
776        }
777    }
778
779    fn as_value_ref(&self) -> ValueRef<'_> {
780        fn helper<'a>(v: &'a JsonVariantRef) -> ValueRef<'a> {
781            match v {
782                JsonVariantRef::Null => ValueRef::Null,
783                JsonVariantRef::Bool(x) => ValueRef::Boolean(*x),
784                JsonVariantRef::Number(x) => match x {
785                    JsonNumber::PosInt(i) => ValueRef::UInt64(*i),
786                    JsonNumber::NegInt(i) => ValueRef::Int64(*i),
787                    JsonNumber::Float(f) => ValueRef::Float64(*f),
788                },
789                JsonVariantRef::String(x) => ValueRef::String(x),
790                JsonVariantRef::Array(array) => {
791                    let val = array.iter().map(helper).collect::<Vec<_>>();
792                    let item_datatype = if let Some(first) = val.first() {
793                        first.data_type()
794                    } else {
795                        ConcreteDataType::null_datatype()
796                    };
797                    ValueRef::List(ListValueRef::RefList {
798                        val,
799                        item_datatype: Arc::new(item_datatype),
800                    })
801                }
802                JsonVariantRef::Object(object) => {
803                    let mut fields = Vec::with_capacity(object.len());
804                    let mut val = Vec::with_capacity(object.len());
805                    for (k, v) in object.iter() {
806                        let v = helper(v);
807                        fields.push(StructField::new(k.to_string(), v.data_type(), true));
808                        val.push(v);
809                    }
810                    ValueRef::Struct(StructValueRef::RefList {
811                        val,
812                        fields: StructType::new(Arc::new(fields)),
813                    })
814                }
815                JsonVariantRef::Variant(x) => ValueRef::Binary(x),
816            }
817        }
818        helper(&self.json_variant)
819    }
820
821    pub(crate) fn data_size(&self) -> usize {
822        size_of_val(self)
823    }
824
825    pub(crate) fn variant(&self) -> &JsonVariantRef<'a> {
826        &self.json_variant
827    }
828
829    pub(crate) fn as_struct_value(&self) -> ValueRef<'_> {
830        if self.is_object() {
831            return self.as_value_ref();
832        }
833
834        ValueRef::Struct(StructValueRef::RefList {
835            val: vec![self.as_value_ref()],
836            fields: self.json_type().as_struct_type(),
837        })
838    }
839}
840
841impl<'a, T: Into<JsonVariantRef<'a>>> From<T> for JsonValueRef<'a> {
842    fn from(v: T) -> Self {
843        Self {
844            json_type: OnceLock::new(),
845            json_variant: v.into(),
846        }
847    }
848}
849
850impl From<JsonValueRef<'_>> for JsonValue {
851    fn from(v: JsonValueRef<'_>) -> Self {
852        Self {
853            json_type: OnceLock::new(),
854            json_variant: v.json_variant.into(),
855        }
856    }
857}
858
859impl PartialEq for JsonValueRef<'_> {
860    fn eq(&self, other: &Self) -> bool {
861        let Self {
862            json_type: _,
863            json_variant,
864        } = self;
865        json_variant == &other.json_variant
866    }
867}
868
869impl Eq for JsonValueRef<'_> {}
870
871impl Clone for JsonValueRef<'_> {
872    fn clone(&self) -> Self {
873        let Self {
874            json_type: _,
875            json_variant,
876        } = self;
877        Self {
878            json_type: OnceLock::new(),
879            json_variant: json_variant.clone(),
880        }
881    }
882}
883
884#[cfg(test)]
885mod tests {
886    use super::*;
887    use crate::types::json_type::JsonObjectType;
888
889    #[test]
890    fn test_align_json_value() -> Result<()> {
891        fn parse_json_value(json: &str) -> JsonValue {
892            let value: serde_json::Value = serde_json::from_str(json).unwrap();
893            value.into()
894        }
895
896        // Root type can be aligned to Null, and the cached json_type must be refreshed.
897        let mut value = JsonValue::from(true);
898        assert_eq!(
899            value.json_type(),
900            &JsonType::new_json2(JsonNativeType::Bool)
901        );
902        value.try_align(&JsonType::null())?;
903        assert_eq!(value, JsonValue::null());
904        assert_eq!(value.json_type(), &JsonType::null());
905
906        // Object alignment now requires the expected type to be a superset of the
907        // value fields, while still filling missing expected fields with null.
908        let expected = JsonType::new_json2(JsonNativeType::Object(JsonObjectType::from([
909            ("extra".to_string(), JsonNativeType::u64()),
910            (
911                "items".to_string(),
912                JsonNativeType::Array(Box::new(JsonNativeType::Object(JsonObjectType::from([
913                    ("id".to_string(), JsonNativeType::u64()),
914                    ("payload".to_string(), JsonNativeType::Variant),
915                    ("note".to_string(), JsonNativeType::String),
916                ])))),
917            ),
918            ("name".to_string(), JsonNativeType::String),
919        ])));
920        let mut value = parse_json_value(r#"{"items":[{"id":1,"payload":{"k":"v"}}],"extra":1}"#);
921        assert_ne!(value.json_type(), &expected);
922        value.try_align(&expected)?;
923        assert_eq!(
924            value,
925            JsonValue::from(JsonVariant::Object(BTreeMap::from([
926                ("extra".to_string(), JsonVariant::from(1_u64)),
927                (
928                    "items".to_string(),
929                    JsonVariant::Array(vec![JsonVariant::Object(BTreeMap::from([
930                        ("id".to_string(), JsonVariant::from(1_u64)),
931                        ("note".to_string(), JsonVariant::Null),
932                        (
933                            "payload".to_string(),
934                            JsonVariant::Variant(br#"{"k":"v"}"#.to_vec()),
935                        ),
936                    ]))]),
937                ),
938                ("name".to_string(), JsonVariant::Null),
939            ])))
940        );
941        assert_eq!(value.json_type(), &expected);
942
943        // Object alignment should fail if the expected type misses any field from the value.
944        let expected = JsonType::new_json2(JsonNativeType::Object(JsonObjectType::from([(
945            "items".to_string(),
946            JsonNativeType::Array(Box::new(JsonNativeType::Object(JsonObjectType::from([
947                ("id".to_string(), JsonNativeType::u64()),
948                ("payload".to_string(), JsonNativeType::Variant),
949            ])))),
950        )])));
951        let mut value =
952            parse_json_value(r#"{"items":[{"id":1,"payload":{"k":"v"},"extra":true}]}"#);
953        let err = value.try_align(&expected).unwrap_err();
954        assert_eq!(
955            err.to_string(),
956            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 } }'"#
957        );
958
959        // Root-level Variant alignment should preserve the original JSON payload.
960        let mut value = parse_json_value(r#"{"foo":[1,true,null]}"#);
961        value.try_align(&JsonType::new_json2(JsonNativeType::Variant))?;
962        assert_eq!(
963            value,
964            JsonValue::from(JsonVariant::Variant(br#"{"foo":[1,true,null]}"#.to_vec()))
965        );
966
967        // Incompatible scalar alignment should fail instead of coercing the value.
968        let mut value = JsonValue::from("hello");
969        let err = value
970            .try_align(&JsonType::new_json2(JsonNativeType::Bool))
971            .unwrap_err();
972        assert_eq!(
973            err.to_string(),
974            r#"Failed to align JSON value, reason: unable to align 'hello' of type "<String>" to type "<Bool>""#
975        );
976
977        Ok(())
978    }
979}