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