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