1use std::collections::BTreeMap;
16use std::fmt::{Debug, Display, Formatter};
17use std::sync::Arc;
18
19use arrow::datatypes::DataType as ArrowDataType;
20use arrow_schema::{Field, Fields};
21use common_base::bytes::Bytes;
22use serde::{Deserialize, Serialize};
23
24use crate::Error;
25use crate::data_type::DataType;
26use crate::error::{InvalidJsonSnafu, InvalidJsonbSnafu, Result, UnsupportedArrowTypeSnafu};
27use crate::prelude::ConcreteDataType;
28use crate::scalars::ScalarVectorBuilder;
29use crate::type_id::LogicalTypeId;
30use crate::value::Value;
31use crate::vectors::json::builder::JsonVectorBuilder;
32use crate::vectors::{BinaryVectorBuilder, MutableVector};
33
34pub const JSON_TYPE_NAME: &str = "Json";
35const JSON2_TYPE_NAME: &str = "Json2";
36
37pub type JsonObjectType = BTreeMap<String, JsonNativeType>;
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
40pub enum JsonNumberType {
41 U64,
42 I64,
43 F64,
44}
45
46#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default)]
47pub enum JsonNativeType {
48 #[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 pub 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 pub fn is_primitive(&self) -> bool {
149 matches!(
150 self,
151 JsonNativeType::Bool | JsonNativeType::Number(_) | JsonNativeType::String
152 )
153 }
154}
155
156impl From<&ConcreteDataType> for JsonNativeType {
157 fn from(value: &ConcreteDataType) -> Self {
158 match value {
159 ConcreteDataType::Null(_) => JsonNativeType::Null,
160 ConcreteDataType::Boolean(_) => JsonNativeType::Bool,
161 ConcreteDataType::UInt64(_)
162 | ConcreteDataType::UInt32(_)
163 | ConcreteDataType::UInt16(_)
164 | ConcreteDataType::UInt8(_) => JsonNativeType::u64(),
165 ConcreteDataType::Int64(_)
166 | ConcreteDataType::Int32(_)
167 | ConcreteDataType::Int16(_)
168 | ConcreteDataType::Int8(_) => JsonNativeType::i64(),
169 ConcreteDataType::Float64(_) | ConcreteDataType::Float32(_) => JsonNativeType::f64(),
170 ConcreteDataType::String(_) => JsonNativeType::String,
171 ConcreteDataType::List(list_type) => {
172 JsonNativeType::Array(Box::new(JsonNativeType::from(list_type.item_type())))
173 }
174 ConcreteDataType::Struct(struct_type) => JsonNativeType::Object(
175 struct_type
176 .fields()
177 .iter()
178 .map(|field| (field.name().to_string(), field.data_type().into()))
179 .collect(),
180 ),
181 ConcreteDataType::Json(json_type) => json_type.native_type().clone(),
182 ConcreteDataType::Binary(_) => JsonNativeType::Variant,
183 _ => unreachable!(),
184 }
185 }
186}
187
188impl TryFrom<&ArrowDataType> for JsonNativeType {
189 type Error = Error;
190
191 fn try_from(t: &ArrowDataType) -> Result<Self> {
192 let t = match t {
193 ArrowDataType::Null => JsonNativeType::Null,
194 ArrowDataType::Boolean => JsonNativeType::Bool,
195 ArrowDataType::Int8
196 | ArrowDataType::Int16
197 | ArrowDataType::Int32
198 | ArrowDataType::Int64 => JsonNativeType::i64(),
199 ArrowDataType::UInt8
200 | ArrowDataType::UInt16
201 | ArrowDataType::UInt32
202 | ArrowDataType::UInt64 => JsonNativeType::u64(),
203 ArrowDataType::Float16 | ArrowDataType::Float32 | ArrowDataType::Float64 => {
204 JsonNativeType::f64()
205 }
206 ArrowDataType::Binary
207 | ArrowDataType::FixedSizeBinary(_)
208 | ArrowDataType::LargeBinary
209 | ArrowDataType::BinaryView => JsonNativeType::Variant,
210 ArrowDataType::Utf8 | ArrowDataType::LargeUtf8 | ArrowDataType::Utf8View => {
211 JsonNativeType::String
212 }
213 ArrowDataType::List(field)
214 | ArrowDataType::ListView(field)
215 | ArrowDataType::FixedSizeList(field, _)
216 | ArrowDataType::LargeList(field)
217 | ArrowDataType::LargeListView(field) => {
218 JsonNativeType::Array(Box::new(Self::try_from(field.data_type())?))
219 }
220 ArrowDataType::Struct(fields) => {
221 let mut object = JsonObjectType::new();
222 for field in fields {
223 object.insert(field.name().clone(), Self::try_from(field.data_type())?);
224 }
225 JsonNativeType::Object(object)
226 }
227 t => {
228 return UnsupportedArrowTypeSnafu {
229 arrow_type: t.clone(),
230 }
231 .fail();
232 }
233 };
234 Ok(t)
235 }
236}
237
238impl Display for JsonNativeType {
239 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
240 match self {
241 JsonNativeType::Null => write!(f, r#""<Null>""#),
242 JsonNativeType::Bool => write!(f, r#""<Bool>""#),
243 JsonNativeType::Number(_) => {
244 write!(f, r#""<Number>""#)
245 }
246 JsonNativeType::String => write!(f, r#""<String>""#),
247 JsonNativeType::Array(item_type) => write!(f, "[{}]", item_type),
248 JsonNativeType::Object(object) => {
249 write!(
250 f,
251 "{{{}}}",
252 object
253 .iter()
254 .map(|(k, v)| format!(r#""{k}":{v}"#))
255 .collect::<Vec<_>>()
256 .join(",")
257 )
258 }
259 JsonNativeType::Variant => write!(f, r#""<Variant>""#),
260 }
261 }
262}
263
264#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default)]
265pub enum JsonFormat {
266 #[default]
267 Jsonb,
268 Json2(Arc<JsonNativeType>),
269}
270
271#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
274pub struct JsonType {
275 pub format: JsonFormat,
276}
277
278impl JsonType {
279 pub fn new(format: JsonFormat) -> Self {
280 Self { format }
281 }
282
283 pub(crate) fn json2(json_type: Arc<JsonNativeType>) -> Self {
284 Self {
285 format: JsonFormat::Json2(json_type),
286 }
287 }
288
289 pub fn is_json2(&self) -> bool {
290 matches!(self.format, JsonFormat::Json2(_))
291 }
292
293 pub fn native_type(&self) -> &JsonNativeType {
295 match &self.format {
296 JsonFormat::Jsonb => &JsonNativeType::String,
297 JsonFormat::Json2(x) => x.as_ref(),
298 }
299 }
300
301 pub fn null() -> Self {
302 Self::json2(Arc::new(JsonNativeType::Null))
303 }
304
305 pub fn is_include(&self, other: &JsonType) -> bool {
307 match (&self.format, &other.format) {
308 (JsonFormat::Jsonb, JsonFormat::Jsonb) => true,
309 (JsonFormat::Json2(this), JsonFormat::Json2(that)) => is_include(this, that),
310 _ => false,
311 }
312 }
313}
314
315pub(crate) fn is_include(this: &JsonNativeType, that: &JsonNativeType) -> bool {
316 fn is_include_object(this: &JsonObjectType, that: &JsonObjectType) -> bool {
317 for (type_name, that_type) in that {
318 let Some(this_type) = this.get(type_name) else {
319 return false;
320 };
321 if !is_include(this_type, that_type) {
322 return false;
323 }
324 }
325 true
326 }
327
328 match (this, that) {
329 (this, that) if this == that => true,
330 (JsonNativeType::Array(this), JsonNativeType::Array(that)) => is_include(this, that),
331 (JsonNativeType::Object(this), JsonNativeType::Object(that)) => {
332 is_include_object(this, that)
333 }
334 (_, JsonNativeType::Null) => true,
335 _ => false,
336 }
337}
338
339impl DataType for JsonType {
340 fn name(&self) -> String {
341 match &self.format {
342 JsonFormat::Jsonb => JSON_TYPE_NAME.to_string(),
343 JsonFormat::Json2(ty) => {
344 format!("{JSON2_TYPE_NAME}{}", ty)
345 }
346 }
347 }
348
349 fn logical_type_id(&self) -> LogicalTypeId {
350 LogicalTypeId::Json
351 }
352
353 fn default_value(&self) -> Value {
354 Bytes::default().into()
355 }
356
357 fn as_arrow_type(&self) -> ArrowDataType {
358 match &self.format {
359 JsonFormat::Jsonb => ArrowDataType::Binary,
360 JsonFormat::Json2(x) => {
361 let mut object = JsonNativeType::object();
362 object.merge(x.as_ref());
363 object.as_arrow_type()
364 }
365 }
366 }
367
368 fn create_mutable_vector(&self, capacity: usize) -> Box<dyn MutableVector> {
369 match &self.format {
370 JsonFormat::Jsonb => Box::new(BinaryVectorBuilder::with_capacity(capacity)),
371 JsonFormat::Json2(x) => Box::new(JsonVectorBuilder::new(x.as_ref().clone(), capacity)),
373 }
374 }
375
376 fn try_cast(&self, from: Value) -> Option<Value> {
377 match from {
378 Value::Binary(v) => Some(Value::Binary(v)),
379 _ => None,
380 }
381 }
382}
383
384impl Display for JsonType {
385 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
386 write!(f, "{}", self.name())
387 }
388}
389
390pub fn jsonb_to_string(val: &[u8]) -> Result<String> {
400 if val.is_empty() {
401 return Ok("".to_string());
402 }
403 match serde_json::to_string(&jsonb::RawJsonb::new(val)) {
404 Ok(s) => Ok(s),
405 Err(jsonb_err) => {
406 let value = jsonb::parse_value(val).map_err(|text_err| {
407 InvalidJsonSnafu {
408 value: format!("neither jsonb ({jsonb_err}) nor JSON text ({text_err})"),
409 }
410 .build()
411 })?;
412 serde_json::to_string(&jsonb::RawJsonb::new(&value.to_vec())).map_err(|e| {
413 InvalidJsonSnafu {
414 value: e.to_string(),
415 }
416 .build()
417 })
418 }
419 }
420}
421
422pub fn jsonb_to_serde_json(val: &[u8]) -> Result<serde_json::Value> {
424 jsonb::from_slice(val)
425 .map(Into::into)
426 .map_err(|error| InvalidJsonbSnafu { error }.build())
427}
428
429pub fn parse_string_to_jsonb(s: &str) -> Result<Vec<u8>> {
431 jsonb::parse_value_standard_mode(s.as_bytes())
432 .map_err(|_| InvalidJsonSnafu { value: s }.build())
433 .map(|json| json.to_vec())
434}
435
436#[cfg(test)]
437mod tests {
438 #[test]
439 fn test_parse_json_rejects_extended_syntax() {
440 for input in ["+1", "01", ".5", "[1,,2]", "{'a':1}"] {
441 assert!(parse_string_to_jsonb(input).is_err(), "{input}");
442 }
443 }
444
445 #[test]
446 fn test_v2_jsonb_to_serde_json_escaped_keys()
447 -> std::result::Result<(), Box<dyn std::error::Error>> {
448 let expected = serde_json::json!({"": 9, "a\"b": {"a\\b": "\u{1f600}\n"}});
449 let input = expected.to_string();
450 let value = jsonb::parse_value(input.as_bytes()).map_err(|e| e.to_string())?;
451 assert_eq!(jsonb_to_serde_json(&value.to_vec())?, expected);
452 Ok(())
453 }
454
455 #[test]
456 fn test_jsonb_to_serde_json_scalars() {
457 for input in [r#""2026-11-05""#, "1730800000000", "false", "null"] {
458 let expected: serde_json::Value = serde_json::from_str(input).unwrap();
459 let jsonb = parse_string_to_jsonb(input).unwrap();
460 assert_eq!(jsonb_to_serde_json(&jsonb).unwrap(), expected, "{input}");
461 assert_eq!(
463 jsonb_to_serde_json(input.as_bytes()).unwrap(),
464 expected,
465 "{input}"
466 );
467 }
468 }
469
470 #[test]
471 fn test_jsonb_to_string_escapes_object_keys()
472 -> std::result::Result<(), Box<dyn std::error::Error>> {
473 let expected = serde_json::json!({
474 "": 1,
475 "a\"b": {"c\\d": ["x", {"e\nf\tg\u{1}": true}], "h": null},
476 "plain": "v\"q",
477 });
478 let input = expected.to_string();
479 let value = jsonb::parse_value(input.as_bytes()).map_err(|e| e.to_string())?;
480 let text = jsonb_to_string(&value.to_vec())?;
481 assert_eq!(serde_json::from_str::<serde_json::Value>(&text)?, expected);
482 assert!(text.contains(r#""a\"b":"#), "{text}");
483 Ok(())
484 }
485
486 #[test]
487 fn test_jsonb_to_string_preserves_literal_unicode_escape_key() {
488 let input = r#"{"\\u{1f600}":"value"}"#;
489 let bytes = parse_string_to_jsonb(input).unwrap();
490 let text = jsonb_to_string(&bytes).unwrap();
491 assert_eq!(
492 serde_json::from_str::<serde_json::Value>(&text).unwrap(),
493 serde_json::from_str::<serde_json::Value>(input).unwrap(),
494 );
495
496 let input = r#"{"\\u{41}":"value"}"#;
498 let bytes = parse_string_to_jsonb(input).unwrap();
499 let text = jsonb_to_string(&bytes).unwrap();
500 assert_eq!(text, input);
501 }
502
503 #[test]
504 fn test_jsonb_to_string_escapes_string_values() {
505 for input in [
508 r#"{"k":"\\u{1f600}"}"#,
509 r#"{"k":"\\u{41}"}"#,
510 r#"{"k":"a\u0000b"}"#,
511 r#"["\\u{1f600}","\u0000"]"#,
512 ] {
513 let bytes = parse_string_to_jsonb(input).unwrap();
514 let text = jsonb_to_string(&bytes).unwrap();
515 assert_eq!(
516 serde_json::from_str::<serde_json::Value>(&text).unwrap(),
517 serde_json::from_str::<serde_json::Value>(input).unwrap(),
518 "{input} -> {text}"
519 );
520 }
521
522 let bytes = parse_string_to_jsonb("{\"k\":\"a\\u2028b\"}").unwrap();
524 assert_eq!(jsonb_to_string(&bytes).unwrap(), "{\"k\":\"a\u{2028}b\"}");
525 }
526
527 #[test]
528 fn test_jsonb_to_string_rejects_invalid_jsonb() {
529 assert!(jsonb_to_string(&[1, 2, 3, 4]).is_err());
530 assert_eq!(jsonb_to_string(&[]).unwrap(), "");
531
532 let mut truncated = parse_string_to_jsonb(r#"{"k":"value"}"#).unwrap();
533 truncated.pop();
534 assert!(jsonb_to_string(&truncated).is_err());
535 }
536
537 #[test]
538 fn test_jsonb_to_string_accepts_json_text_bytes() {
539 assert_eq!(
541 jsonb_to_string(br#"{"foo":"bar"}"#).unwrap(),
542 r#"{"foo":"bar"}"#
543 );
544 assert_eq!(
545 jsonb_to_string(br#"{"a":null, "foo":"bar"}"#).unwrap(),
546 r#"{"a":null,"foo":"bar"}"#
547 );
548 assert_eq!(
550 jsonb_to_string(br#"{"a\"b":"c\u0000d"}"#).unwrap(),
551 r#"{"a\"b":"c\u0000d"}"#
552 );
553 assert_eq!(
555 jsonb_to_string(br#""hello world""#).unwrap(),
556 r#""hello world""#
557 );
558 assert_eq!(jsonb_to_string(b" null").unwrap(), "null");
559 assert_eq!(
561 jsonb_to_string(br#""2026-11-05""#).unwrap(),
562 r#""2026-11-05""#
563 );
564 assert_eq!(jsonb_to_string(b"1730800000000").unwrap(), "1730800000000");
565 assert_eq!(jsonb_to_string(b"[+1,,2]").unwrap(), "[1,null,2]");
567 assert!(jsonb_to_string(b"{not json").is_err());
568 }
569
570 #[test]
571 fn test_jsonb_to_string_keeps_compact_format() -> Result<()> {
572 let value = jsonb::parse_value(br#"{"b": [1, 2.5, "x"], "a": {"c": false}}"#).unwrap();
573 assert_eq!(
574 jsonb_to_string(&value.to_vec())?,
575 r#"{"a":{"c":false},"b":[1,2.5,"x"]}"#
576 );
577 Ok(())
578 }
579
580 use super::*;
581
582 #[test]
583 fn test_json_type_include() {
584 fn test(this: &JsonNativeType, that: &JsonNativeType, expected: bool) {
585 assert_eq!(is_include(this, that), expected, "this={this}, that={that}");
586 }
587
588 test(&JsonNativeType::Null, &JsonNativeType::Null, true);
589 test(&JsonNativeType::Null, &JsonNativeType::Bool, false);
590 test(&JsonNativeType::Bool, &JsonNativeType::Null, true);
591
592 test(&JsonNativeType::Bool, &JsonNativeType::Bool, true);
593 test(&JsonNativeType::Bool, &JsonNativeType::u64(), false);
594
595 test(&JsonNativeType::u64(), &JsonNativeType::Null, true);
596 test(&JsonNativeType::u64(), &JsonNativeType::u64(), true);
597 test(&JsonNativeType::u64(), &JsonNativeType::String, false);
598
599 test(&JsonNativeType::String, &JsonNativeType::Null, true);
600 test(&JsonNativeType::String, &JsonNativeType::String, true);
601 test(
602 &JsonNativeType::String,
603 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
604 false,
605 );
606
607 test(
608 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
609 &JsonNativeType::Null,
610 true,
611 );
612 test(
613 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
614 &JsonNativeType::Array(Box::new(JsonNativeType::Null)),
615 true,
616 );
617 test(
618 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
619 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
620 true,
621 );
622 test(
623 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
624 &JsonNativeType::String,
625 false,
626 );
627 test(
628 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
629 &JsonNativeType::Object(JsonObjectType::new()),
630 false,
631 );
632
633 let simple_json_object = &JsonNativeType::Object(JsonObjectType::from([(
634 "foo".to_string(),
635 JsonNativeType::String,
636 )]));
637 test(simple_json_object, simple_json_object, true);
638 test(simple_json_object, &JsonNativeType::i64(), false);
639 test(
640 simple_json_object,
641 &JsonNativeType::Object(JsonObjectType::from([(
642 "bar".to_string(),
643 JsonNativeType::i64(),
644 )])),
645 false,
646 );
647
648 let complex_json_object = &JsonNativeType::Object(JsonObjectType::from([
649 (
650 "nested".to_string(),
651 JsonNativeType::Object(JsonObjectType::from([(
652 "a".to_string(),
653 JsonNativeType::Object(JsonObjectType::from([(
654 "b".to_string(),
655 JsonNativeType::Object(JsonObjectType::from([(
656 "c".to_string(),
657 JsonNativeType::String,
658 )])),
659 )])),
660 )])),
661 ),
662 ("bar".to_string(), JsonNativeType::i64()),
663 ]));
664 test(simple_json_object, &JsonNativeType::Null, true);
665 test(complex_json_object, &JsonNativeType::String, false);
666 test(complex_json_object, complex_json_object, true);
667 test(
668 complex_json_object,
669 &JsonNativeType::Object(JsonObjectType::from([(
670 "bar".to_string(),
671 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::Null,
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::String,
697 )])),
698 ),
699 ("bar".to_string(), JsonNativeType::i64()),
700 ])),
701 false,
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::String,
713 )])),
714 )])),
715 ),
716 ("bar".to_string(), JsonNativeType::i64()),
717 ])),
718 false,
719 );
720 test(
721 complex_json_object,
722 &JsonNativeType::Object(JsonObjectType::from([
723 (
724 "nested".to_string(),
725 JsonNativeType::Object(JsonObjectType::from([(
726 "a".to_string(),
727 JsonNativeType::Object(JsonObjectType::from([(
728 "b".to_string(),
729 JsonNativeType::Object(JsonObjectType::from([(
730 "c".to_string(),
731 JsonNativeType::Null,
732 )])),
733 )])),
734 )])),
735 ),
736 ("bar".to_string(), JsonNativeType::i64()),
737 ])),
738 true,
739 );
740 test(
741 complex_json_object,
742 &JsonNativeType::Object(JsonObjectType::from([
743 (
744 "nested".to_string(),
745 JsonNativeType::Object(JsonObjectType::from([(
746 "a".to_string(),
747 JsonNativeType::Object(JsonObjectType::from([(
748 "b".to_string(),
749 JsonNativeType::Object(JsonObjectType::from([(
750 "c".to_string(),
751 JsonNativeType::Bool,
752 )])),
753 )])),
754 )])),
755 ),
756 ("bar".to_string(), JsonNativeType::i64()),
757 ])),
758 false,
759 );
760 test(
761 complex_json_object,
762 &JsonNativeType::Object(JsonObjectType::from([(
763 "nested".to_string(),
764 JsonNativeType::Object(JsonObjectType::from([(
765 "a".to_string(),
766 JsonNativeType::Object(JsonObjectType::from([(
767 "b".to_string(),
768 JsonNativeType::Object(JsonObjectType::from([(
769 "c".to_string(),
770 JsonNativeType::String,
771 )])),
772 )])),
773 )])),
774 )])),
775 true,
776 );
777 }
778
779 #[test]
780 fn test_merge_json_type() {
781 fn test(other: JsonNativeType, json_type: &mut JsonNativeType, expected: &str) {
782 json_type.merge(&other);
783 assert_eq!(json_type.to_string(), expected);
784 }
785
786 test(
788 JsonNativeType::Bool,
789 &mut JsonNativeType::Null,
790 r#""<Bool>""#,
791 );
792
793 test(
795 JsonNativeType::Null,
796 &mut JsonNativeType::Bool,
797 r#""<Bool>""#,
798 );
799
800 test(
802 JsonNativeType::i64(),
803 &mut JsonNativeType::i64(),
804 r#""<Number>""#,
805 );
806
807 for (mut this, other) in [
809 (JsonNativeType::u64(), JsonNativeType::i64()),
810 (JsonNativeType::u64(), JsonNativeType::f64()),
811 (JsonNativeType::i64(), JsonNativeType::f64()),
812 ] {
813 test(other, &mut this, r#""<Variant>""#);
814 }
815
816 test(
818 JsonNativeType::Object(JsonObjectType::from([(
819 "foo".to_string(),
820 JsonNativeType::String,
821 )])),
822 &mut JsonNativeType::Object(JsonObjectType::from([(
823 "bar".to_string(),
824 JsonNativeType::i64(),
825 )])),
826 r#"{"bar":"<Number>","foo":"<String>"}"#,
827 );
828
829 test(
831 JsonNativeType::Object(JsonObjectType::from([(
832 "foo".to_string(),
833 JsonNativeType::i64(),
834 )])),
835 &mut JsonNativeType::Object(JsonObjectType::from([(
836 "foo".to_string(),
837 JsonNativeType::Bool,
838 )])),
839 r#"{"foo":"<Variant>"}"#,
840 );
841
842 test(
844 JsonNativeType::Object(JsonObjectType::from([(
845 "nested".to_string(),
846 JsonNativeType::Object(JsonObjectType::from([(
847 "foo".to_string(),
848 JsonNativeType::String,
849 )])),
850 )])),
851 &mut JsonNativeType::Object(JsonObjectType::from([(
852 "nested".to_string(),
853 JsonNativeType::Object(JsonObjectType::from([(
854 "bar".to_string(),
855 JsonNativeType::Bool,
856 )])),
857 )])),
858 r#"{"nested":{"bar":"<Bool>","foo":"<String>"}}"#,
859 );
860
861 test(
863 JsonNativeType::Array(Box::new(JsonNativeType::String)),
864 &mut JsonNativeType::Array(Box::new(JsonNativeType::u64())),
865 r#"["<Variant>"]"#,
866 );
867
868 test(
870 JsonNativeType::Object(JsonObjectType::from([(
871 "foo".to_string(),
872 JsonNativeType::String,
873 )])),
874 &mut JsonNativeType::Bool,
875 r#""<Variant>""#,
876 );
877 }
878}