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