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