1use std::collections::BTreeMap;
16use std::fmt::{Debug, Display, Formatter};
17use std::str::FromStr;
18use std::sync::{Arc, LazyLock};
19
20use arrow::datatypes::DataType as ArrowDataType;
21use arrow_schema::{Field, Fields};
22use common_base::bytes::Bytes;
23use regex::{Captures, Regex};
24use serde::{Deserialize, Serialize};
25use snafu::ResultExt;
26
27use crate::Error;
28use crate::data_type::DataType;
29use crate::error::{
30 DeserializeSnafu, InvalidJsonSnafu, InvalidJsonbSnafu, Result, UnsupportedArrowTypeSnafu,
31};
32use crate::prelude::ConcreteDataType;
33use crate::scalars::ScalarVectorBuilder;
34use crate::type_id::LogicalTypeId;
35use crate::value::Value;
36use crate::vectors::json::builder::JsonVectorBuilder;
37use crate::vectors::{BinaryVectorBuilder, MutableVector};
38
39pub const JSON_TYPE_NAME: &str = "Json";
40const JSON2_TYPE_NAME: &str = "Json2";
41
42pub type JsonObjectType = BTreeMap<String, JsonNativeType>;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
45pub enum JsonNumberType {
46 U64,
47 I64,
48 F64,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default)]
52pub enum JsonNativeType {
53 #[default]
59 Null,
60 Bool,
61 Number(JsonNumberType),
62 String,
63 Array(Box<JsonNativeType>),
64 Object(JsonObjectType),
65 Variant,
69}
70
71impl JsonNativeType {
72 pub fn is_null(&self) -> bool {
73 matches!(self, JsonNativeType::Null)
74 }
75
76 pub fn u64() -> Self {
77 Self::Number(JsonNumberType::U64)
78 }
79
80 pub fn i64() -> Self {
81 Self::Number(JsonNumberType::I64)
82 }
83
84 pub fn f64() -> Self {
85 Self::Number(JsonNumberType::F64)
86 }
87
88 pub fn object() -> Self {
89 Self::Object(JsonObjectType::new())
90 }
91
92 pub fn merge(&mut self, other: &JsonNativeType) {
95 if self == other {
96 return;
97 }
98
99 fn merge_object(this: &mut JsonObjectType, that: &JsonObjectType) {
100 for (type_name, that_type) in that {
102 if let Some(this_type) = this.get_mut(type_name) {
103 this_type.merge(that_type);
104 } else {
105 this.insert(type_name.clone(), that_type.clone());
106 }
107 }
108 }
109
110 let zelf = std::mem::take(self);
111 *self = match (zelf, other) {
112 (JsonNativeType::Object(mut this), JsonNativeType::Object(that)) => {
113 merge_object(&mut this, that);
114 JsonNativeType::Object(this)
115 }
116 (JsonNativeType::Array(mut this), JsonNativeType::Array(that)) => {
117 this.merge(that);
118 JsonNativeType::Array(this)
119 }
120 (JsonNativeType::Null, that) => that.clone(),
121 (this, JsonNativeType::Null) => this,
122 (this, that) if this == *that => this,
123
124 _ => JsonNativeType::Variant,
125 };
126 }
127
128 pub fn as_arrow_type(&self) -> ArrowDataType {
129 match self {
130 JsonNativeType::Null => ArrowDataType::Null,
131 JsonNativeType::Bool => ArrowDataType::Boolean,
132 JsonNativeType::Number(n) => match n {
133 JsonNumberType::U64 => ArrowDataType::UInt64,
134 JsonNumberType::I64 => ArrowDataType::Int64,
135 JsonNumberType::F64 => ArrowDataType::Float64,
136 },
137 JsonNativeType::String => ArrowDataType::Utf8View,
138 JsonNativeType::Array(array) => {
139 ArrowDataType::List(Arc::new(Field::new("item", array.as_arrow_type(), true)))
140 }
141 JsonNativeType::Object(object) => {
142 let fields = object
143 .iter()
144 .map(|(k, v)| Arc::new(Field::new(k, v.as_arrow_type(), true)))
145 .collect::<Vec<_>>();
146 ArrowDataType::Struct(Fields::from(fields))
147 }
148 JsonNativeType::Variant => ArrowDataType::Binary,
149 }
150 }
151
152 pub fn is_primitive(&self) -> bool {
154 matches!(
155 self,
156 JsonNativeType::Bool | JsonNativeType::Number(_) | JsonNativeType::String
157 )
158 }
159}
160
161impl From<&ConcreteDataType> for JsonNativeType {
162 fn from(value: &ConcreteDataType) -> Self {
163 match value {
164 ConcreteDataType::Null(_) => JsonNativeType::Null,
165 ConcreteDataType::Boolean(_) => JsonNativeType::Bool,
166 ConcreteDataType::UInt64(_)
167 | ConcreteDataType::UInt32(_)
168 | ConcreteDataType::UInt16(_)
169 | ConcreteDataType::UInt8(_) => JsonNativeType::u64(),
170 ConcreteDataType::Int64(_)
171 | ConcreteDataType::Int32(_)
172 | ConcreteDataType::Int16(_)
173 | ConcreteDataType::Int8(_) => JsonNativeType::i64(),
174 ConcreteDataType::Float64(_) | ConcreteDataType::Float32(_) => JsonNativeType::f64(),
175 ConcreteDataType::String(_) => JsonNativeType::String,
176 ConcreteDataType::List(list_type) => {
177 JsonNativeType::Array(Box::new(JsonNativeType::from(list_type.item_type())))
178 }
179 ConcreteDataType::Struct(struct_type) => JsonNativeType::Object(
180 struct_type
181 .fields()
182 .iter()
183 .map(|field| (field.name().to_string(), field.data_type().into()))
184 .collect(),
185 ),
186 ConcreteDataType::Json(json_type) => json_type.native_type().clone(),
187 ConcreteDataType::Binary(_) => JsonNativeType::Variant,
188 _ => unreachable!(),
189 }
190 }
191}
192
193impl TryFrom<&ArrowDataType> for JsonNativeType {
194 type Error = Error;
195
196 fn try_from(t: &ArrowDataType) -> Result<Self> {
197 let t = match t {
198 ArrowDataType::Null => JsonNativeType::Null,
199 ArrowDataType::Boolean => JsonNativeType::Bool,
200 ArrowDataType::Int8
201 | ArrowDataType::Int16
202 | ArrowDataType::Int32
203 | ArrowDataType::Int64 => JsonNativeType::i64(),
204 ArrowDataType::UInt8
205 | ArrowDataType::UInt16
206 | ArrowDataType::UInt32
207 | ArrowDataType::UInt64 => JsonNativeType::u64(),
208 ArrowDataType::Float16 | ArrowDataType::Float32 | ArrowDataType::Float64 => {
209 JsonNativeType::f64()
210 }
211 ArrowDataType::Binary
212 | ArrowDataType::FixedSizeBinary(_)
213 | ArrowDataType::LargeBinary
214 | ArrowDataType::BinaryView => JsonNativeType::Variant,
215 ArrowDataType::Utf8 | ArrowDataType::LargeUtf8 | ArrowDataType::Utf8View => {
216 JsonNativeType::String
217 }
218 ArrowDataType::List(field)
219 | ArrowDataType::ListView(field)
220 | ArrowDataType::FixedSizeList(field, _)
221 | ArrowDataType::LargeList(field)
222 | ArrowDataType::LargeListView(field) => {
223 JsonNativeType::Array(Box::new(Self::try_from(field.data_type())?))
224 }
225 ArrowDataType::Struct(fields) => {
226 let mut object = JsonObjectType::new();
227 for field in fields {
228 object.insert(field.name().clone(), Self::try_from(field.data_type())?);
229 }
230 JsonNativeType::Object(object)
231 }
232 t => {
233 return UnsupportedArrowTypeSnafu {
234 arrow_type: t.clone(),
235 }
236 .fail();
237 }
238 };
239 Ok(t)
240 }
241}
242
243impl Display for JsonNativeType {
244 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
245 match self {
246 JsonNativeType::Null => write!(f, r#""<Null>""#),
247 JsonNativeType::Bool => write!(f, r#""<Bool>""#),
248 JsonNativeType::Number(_) => {
249 write!(f, r#""<Number>""#)
250 }
251 JsonNativeType::String => write!(f, r#""<String>""#),
252 JsonNativeType::Array(item_type) => write!(f, "[{}]", item_type),
253 JsonNativeType::Object(object) => {
254 write!(
255 f,
256 "{{{}}}",
257 object
258 .iter()
259 .map(|(k, v)| format!(r#""{k}":{v}"#))
260 .collect::<Vec<_>>()
261 .join(",")
262 )
263 }
264 JsonNativeType::Variant => write!(f, r#""<Variant>""#),
265 }
266 }
267}
268
269#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default)]
270pub enum JsonFormat {
271 #[default]
272 Jsonb,
273 Json2(Arc<JsonNativeType>),
274}
275
276#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
279pub struct JsonType {
280 pub format: JsonFormat,
281}
282
283impl JsonType {
284 pub fn new(format: JsonFormat) -> Self {
285 Self { format }
286 }
287
288 pub(crate) fn json2(json_type: Arc<JsonNativeType>) -> Self {
289 Self {
290 format: JsonFormat::Json2(json_type),
291 }
292 }
293
294 pub fn is_json2(&self) -> bool {
295 matches!(self.format, JsonFormat::Json2(_))
296 }
297
298 pub fn native_type(&self) -> &JsonNativeType {
300 match &self.format {
301 JsonFormat::Jsonb => &JsonNativeType::String,
302 JsonFormat::Json2(x) => x.as_ref(),
303 }
304 }
305
306 pub fn null() -> Self {
307 Self::json2(Arc::new(JsonNativeType::Null))
308 }
309
310 pub fn is_include(&self, other: &JsonType) -> bool {
312 match (&self.format, &other.format) {
313 (JsonFormat::Jsonb, JsonFormat::Jsonb) => true,
314 (JsonFormat::Json2(this), JsonFormat::Json2(that)) => is_include(this, that),
315 _ => false,
316 }
317 }
318}
319
320pub(crate) fn is_include(this: &JsonNativeType, that: &JsonNativeType) -> bool {
321 fn is_include_object(this: &JsonObjectType, that: &JsonObjectType) -> bool {
322 for (type_name, that_type) in that {
323 let Some(this_type) = this.get(type_name) else {
324 return false;
325 };
326 if !is_include(this_type, that_type) {
327 return false;
328 }
329 }
330 true
331 }
332
333 match (this, that) {
334 (this, that) if this == that => true,
335 (JsonNativeType::Array(this), JsonNativeType::Array(that)) => is_include(this, that),
336 (JsonNativeType::Object(this), JsonNativeType::Object(that)) => {
337 is_include_object(this, that)
338 }
339 (_, JsonNativeType::Null) => true,
340 _ => false,
341 }
342}
343
344impl DataType for JsonType {
345 fn name(&self) -> String {
346 match &self.format {
347 JsonFormat::Jsonb => JSON_TYPE_NAME.to_string(),
348 JsonFormat::Json2(ty) => {
349 format!("{JSON2_TYPE_NAME}{}", ty)
350 }
351 }
352 }
353
354 fn logical_type_id(&self) -> LogicalTypeId {
355 LogicalTypeId::Json
356 }
357
358 fn default_value(&self) -> Value {
359 Bytes::default().into()
360 }
361
362 fn as_arrow_type(&self) -> ArrowDataType {
363 match &self.format {
364 JsonFormat::Jsonb => ArrowDataType::Binary,
365 JsonFormat::Json2(x) => {
366 let mut object = JsonNativeType::object();
367 object.merge(x.as_ref());
368 object.as_arrow_type()
369 }
370 }
371 }
372
373 fn create_mutable_vector(&self, capacity: usize) -> Box<dyn MutableVector> {
374 match &self.format {
375 JsonFormat::Jsonb => Box::new(BinaryVectorBuilder::with_capacity(capacity)),
376 JsonFormat::Json2(x) => Box::new(JsonVectorBuilder::new(x.as_ref().clone(), capacity)),
378 }
379 }
380
381 fn try_cast(&self, from: Value) -> Option<Value> {
382 match from {
383 Value::Binary(v) => Some(Value::Binary(v)),
384 _ => None,
385 }
386 }
387}
388
389impl Display for JsonType {
390 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
391 write!(f, "{}", self.name())
392 }
393}
394
395pub fn jsonb_to_string(val: &[u8]) -> Result<String> {
397 if val.is_empty() {
398 return Ok("".to_string());
399 }
400 match jsonb::from_slice(val) {
401 Ok(jsonb_value) => {
402 let serialized = jsonb_value.to_string();
403 fix_unicode_point(&serialized)
404 }
405 Err(e) => InvalidJsonbSnafu { error: e }.fail(),
406 }
407}
408
409pub fn jsonb_to_serde_json(val: &[u8]) -> Result<serde_json::Value> {
411 let json_string = jsonb_to_string(val)?;
412 serde_json::Value::from_str(&json_string).context(DeserializeSnafu { json: json_string })
413}
414
415fn fix_unicode_point(json: &str) -> Result<String> {
430 static UNICODE_CODE_POINT_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
431 Regex::new(r"\\u\{([0-9a-fA-F]{1,6})}").unwrap_or_else(|e| panic!("{}", e))
434 });
435
436 let v = UNICODE_CODE_POINT_PATTERN.replace_all(json, |caps: &Captures| {
437 let hex = &caps[1];
439 let Ok(code) = u32::from_str_radix(hex, 16) else {
440 return caps[0].to_string();
442 };
443
444 if code <= 0xFFFF {
445 format!("\\u{:04X}", code)
447 } else if code > 0x10FFFF {
448 caps[0].to_string()
450 } else {
451 let code = code - 0x10000;
454
455 let high = 0xD800 + ((code >> 10) & 0x3FF);
457
458 let low = 0xDC00 + (code & 0x3FF);
460
461 format!("\\u{:04X}\\u{:04X}", high, low)
463 }
464 });
465 Ok(v.to_string())
466}
467
468pub fn parse_string_to_jsonb(s: &str) -> Result<Vec<u8>> {
470 jsonb::parse_value(s.as_bytes())
471 .map_err(|_| InvalidJsonSnafu { value: s }.build())
472 .map(|json| json.to_vec())
473}
474
475#[cfg(test)]
476mod tests {
477 use super::*;
478
479 #[test]
480 fn test_fix_unicode_point() -> Result<()> {
481 let valid_cases = vec![
482 (r#"{"data": "simple ascii"}"#, r#"{"data": "simple ascii"}"#),
483 (
484 r#"{"data":"Greek sigma: \u{03a3}"}"#,
485 r#"{"data":"Greek sigma: \u03A3"}"#,
486 ),
487 (
488 r#"{"data":"Joker card: \u{1f0df}"}"#,
489 r#"{"data":"Joker card: \uD83C\uDCDF"}"#,
490 ),
491 (
492 r#"{"data":"BMP boundary: \u{ffff}"}"#,
493 r#"{"data":"BMP boundary: \uFFFF"}"#,
494 ),
495 (
496 r#"{"data":"Supplementary min: \u{10000}"}"#,
497 r#"{"data":"Supplementary min: \uD800\uDC00"}"#,
498 ),
499 (
500 r#"{"data":"Supplementary max: \u{10ffff}"}"#,
501 r#"{"data":"Supplementary max: \uDBFF\uDFFF"}"#,
502 ),
503 ];
504 for (input, expect) in valid_cases {
505 let v = fix_unicode_point(input)?;
506 assert_eq!(v, expect);
507 }
508
509 let invalid_escape_cases = vec![
510 (
511 r#"{"data": "Invalid hex: \u{gggg}"}"#,
512 r#"{"data": "Invalid hex: \u{gggg}"}"#,
513 ),
514 (
515 r#"{"data": "Empty braces: \u{}"}"#,
516 r#"{"data": "Empty braces: \u{}"}"#,
517 ),
518 (
519 r#"{"data": "Out of range: \u{1100000}"}"#,
520 r#"{"data": "Out of range: \u{1100000}"}"#,
521 ),
522 ];
523 for (input, expect) in invalid_escape_cases {
524 let v = fix_unicode_point(input)?;
525 assert_eq!(v, expect);
526 }
527
528 Ok(())
529 }
530
531 #[test]
532 fn test_json_type_include() {
533 fn test(this: &JsonNativeType, that: &JsonNativeType, expected: bool) {
534 assert_eq!(is_include(this, that), expected, "this={this}, that={that}");
535 }
536
537 test(&JsonNativeType::Null, &JsonNativeType::Null, true);
538 test(&JsonNativeType::Null, &JsonNativeType::Bool, false);
539 test(&JsonNativeType::Bool, &JsonNativeType::Null, true);
540
541 test(&JsonNativeType::Bool, &JsonNativeType::Bool, true);
542 test(&JsonNativeType::Bool, &JsonNativeType::u64(), false);
543
544 test(&JsonNativeType::u64(), &JsonNativeType::Null, true);
545 test(&JsonNativeType::u64(), &JsonNativeType::u64(), true);
546 test(&JsonNativeType::u64(), &JsonNativeType::String, false);
547
548 test(&JsonNativeType::String, &JsonNativeType::Null, true);
549 test(&JsonNativeType::String, &JsonNativeType::String, true);
550 test(
551 &JsonNativeType::String,
552 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
553 false,
554 );
555
556 test(
557 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
558 &JsonNativeType::Null,
559 true,
560 );
561 test(
562 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
563 &JsonNativeType::Array(Box::new(JsonNativeType::Null)),
564 true,
565 );
566 test(
567 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
568 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
569 true,
570 );
571 test(
572 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
573 &JsonNativeType::String,
574 false,
575 );
576 test(
577 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
578 &JsonNativeType::Object(JsonObjectType::new()),
579 false,
580 );
581
582 let simple_json_object = &JsonNativeType::Object(JsonObjectType::from([(
583 "foo".to_string(),
584 JsonNativeType::String,
585 )]));
586 test(simple_json_object, simple_json_object, true);
587 test(simple_json_object, &JsonNativeType::i64(), false);
588 test(
589 simple_json_object,
590 &JsonNativeType::Object(JsonObjectType::from([(
591 "bar".to_string(),
592 JsonNativeType::i64(),
593 )])),
594 false,
595 );
596
597 let complex_json_object = &JsonNativeType::Object(JsonObjectType::from([
598 (
599 "nested".to_string(),
600 JsonNativeType::Object(JsonObjectType::from([(
601 "a".to_string(),
602 JsonNativeType::Object(JsonObjectType::from([(
603 "b".to_string(),
604 JsonNativeType::Object(JsonObjectType::from([(
605 "c".to_string(),
606 JsonNativeType::String,
607 )])),
608 )])),
609 )])),
610 ),
611 ("bar".to_string(), JsonNativeType::i64()),
612 ]));
613 test(simple_json_object, &JsonNativeType::Null, true);
614 test(complex_json_object, &JsonNativeType::String, false);
615 test(complex_json_object, complex_json_object, true);
616 test(
617 complex_json_object,
618 &JsonNativeType::Object(JsonObjectType::from([(
619 "bar".to_string(),
620 JsonNativeType::i64(),
621 )])),
622 true,
623 );
624 test(
625 complex_json_object,
626 &JsonNativeType::Object(JsonObjectType::from([
627 (
628 "nested".to_string(),
629 JsonNativeType::Object(JsonObjectType::from([(
630 "a".to_string(),
631 JsonNativeType::Null,
632 )])),
633 ),
634 ("bar".to_string(), JsonNativeType::i64()),
635 ])),
636 true,
637 );
638 test(
639 complex_json_object,
640 &JsonNativeType::Object(JsonObjectType::from([
641 (
642 "nested".to_string(),
643 JsonNativeType::Object(JsonObjectType::from([(
644 "a".to_string(),
645 JsonNativeType::String,
646 )])),
647 ),
648 ("bar".to_string(), JsonNativeType::i64()),
649 ])),
650 false,
651 );
652 test(
653 complex_json_object,
654 &JsonNativeType::Object(JsonObjectType::from([
655 (
656 "nested".to_string(),
657 JsonNativeType::Object(JsonObjectType::from([(
658 "a".to_string(),
659 JsonNativeType::Object(JsonObjectType::from([(
660 "b".to_string(),
661 JsonNativeType::String,
662 )])),
663 )])),
664 ),
665 ("bar".to_string(), JsonNativeType::i64()),
666 ])),
667 false,
668 );
669 test(
670 complex_json_object,
671 &JsonNativeType::Object(JsonObjectType::from([
672 (
673 "nested".to_string(),
674 JsonNativeType::Object(JsonObjectType::from([(
675 "a".to_string(),
676 JsonNativeType::Object(JsonObjectType::from([(
677 "b".to_string(),
678 JsonNativeType::Object(JsonObjectType::from([(
679 "c".to_string(),
680 JsonNativeType::Null,
681 )])),
682 )])),
683 )])),
684 ),
685 ("bar".to_string(), JsonNativeType::i64()),
686 ])),
687 true,
688 );
689 test(
690 complex_json_object,
691 &JsonNativeType::Object(JsonObjectType::from([
692 (
693 "nested".to_string(),
694 JsonNativeType::Object(JsonObjectType::from([(
695 "a".to_string(),
696 JsonNativeType::Object(JsonObjectType::from([(
697 "b".to_string(),
698 JsonNativeType::Object(JsonObjectType::from([(
699 "c".to_string(),
700 JsonNativeType::Bool,
701 )])),
702 )])),
703 )])),
704 ),
705 ("bar".to_string(), JsonNativeType::i64()),
706 ])),
707 false,
708 );
709 test(
710 complex_json_object,
711 &JsonNativeType::Object(JsonObjectType::from([(
712 "nested".to_string(),
713 JsonNativeType::Object(JsonObjectType::from([(
714 "a".to_string(),
715 JsonNativeType::Object(JsonObjectType::from([(
716 "b".to_string(),
717 JsonNativeType::Object(JsonObjectType::from([(
718 "c".to_string(),
719 JsonNativeType::String,
720 )])),
721 )])),
722 )])),
723 )])),
724 true,
725 );
726 }
727
728 #[test]
729 fn test_merge_json_type() {
730 fn test(other: JsonNativeType, json_type: &mut JsonNativeType, expected: &str) {
731 json_type.merge(&other);
732 assert_eq!(json_type.to_string(), expected);
733 }
734
735 test(
737 JsonNativeType::Bool,
738 &mut JsonNativeType::Null,
739 r#""<Bool>""#,
740 );
741
742 test(
744 JsonNativeType::Null,
745 &mut JsonNativeType::Bool,
746 r#""<Bool>""#,
747 );
748
749 test(
751 JsonNativeType::i64(),
752 &mut JsonNativeType::i64(),
753 r#""<Number>""#,
754 );
755
756 for (mut this, other) in [
758 (JsonNativeType::u64(), JsonNativeType::i64()),
759 (JsonNativeType::u64(), JsonNativeType::f64()),
760 (JsonNativeType::i64(), JsonNativeType::f64()),
761 ] {
762 test(other, &mut this, r#""<Variant>""#);
763 }
764
765 test(
767 JsonNativeType::Object(JsonObjectType::from([(
768 "foo".to_string(),
769 JsonNativeType::String,
770 )])),
771 &mut JsonNativeType::Object(JsonObjectType::from([(
772 "bar".to_string(),
773 JsonNativeType::i64(),
774 )])),
775 r#"{"bar":"<Number>","foo":"<String>"}"#,
776 );
777
778 test(
780 JsonNativeType::Object(JsonObjectType::from([(
781 "foo".to_string(),
782 JsonNativeType::i64(),
783 )])),
784 &mut JsonNativeType::Object(JsonObjectType::from([(
785 "foo".to_string(),
786 JsonNativeType::Bool,
787 )])),
788 r#"{"foo":"<Variant>"}"#,
789 );
790
791 test(
793 JsonNativeType::Object(JsonObjectType::from([(
794 "nested".to_string(),
795 JsonNativeType::Object(JsonObjectType::from([(
796 "foo".to_string(),
797 JsonNativeType::String,
798 )])),
799 )])),
800 &mut JsonNativeType::Object(JsonObjectType::from([(
801 "nested".to_string(),
802 JsonNativeType::Object(JsonObjectType::from([(
803 "bar".to_string(),
804 JsonNativeType::Bool,
805 )])),
806 )])),
807 r#"{"nested":{"bar":"<Bool>","foo":"<String>"}}"#,
808 );
809
810 test(
812 JsonNativeType::Array(Box::new(JsonNativeType::String)),
813 &mut JsonNativeType::Array(Box::new(JsonNativeType::u64())),
814 r#"["<Variant>"]"#,
815 );
816
817 test(
819 JsonNativeType::Object(JsonObjectType::from([(
820 "foo".to_string(),
821 JsonNativeType::String,
822 )])),
823 &mut JsonNativeType::Bool,
824 r#""<Variant>""#,
825 );
826 }
827}