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