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