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