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> {
403 if val.is_empty() {
404 return Ok("".to_string());
405 }
406 match serde_json::to_string(&jsonb::RawJsonb::new(val)) {
407 Ok(s) => Ok(s),
408 Err(e) => match jsonb::parse_value_standard_mode(val) {
409 Ok(json) => serde_json::to_string(&jsonb::RawJsonb::new(&json.to_vec())).map_err(|e| {
410 InvalidJsonSnafu {
411 value: e.to_string(),
412 }
413 .build()
414 }),
415 Err(_) => InvalidJsonSnafu {
416 value: e.to_string(),
417 }
418 .fail(),
419 },
420 }
421}
422
423pub fn jsonb_to_serde_json(val: &[u8]) -> Result<serde_json::Value> {
425 jsonb::from_slice(val)
426 .map(Into::into)
427 .map_err(|error| InvalidJsonbSnafu { error }.build())
428}
429
430pub fn parse_string_to_jsonb(s: &str) -> Result<Vec<u8>> {
432 jsonb::parse_value_standard_mode(s.as_bytes())
433 .map_err(|_| InvalidJsonSnafu { value: s }.build())
434 .map(|json| json.to_vec())
435}
436
437#[cfg(test)]
438mod tests {
439 #[test]
440 fn test_parse_json_rejects_extended_syntax() {
441 for input in ["+1", "01", ".5", "[1,,2]", "{'a':1}"] {
442 assert!(parse_string_to_jsonb(input).is_err(), "{input}");
443 }
444 }
445
446 #[test]
447 fn test_v2_jsonb_to_serde_json_escaped_keys()
448 -> std::result::Result<(), Box<dyn std::error::Error>> {
449 let expected = serde_json::json!({"": 9, "a\"b": {"a\\b": "\u{1f600}\n"}});
450 let input = expected.to_string();
451 let value = jsonb::parse_value(input.as_bytes()).map_err(|e| e.to_string())?;
452 assert_eq!(jsonb_to_serde_json(&value.to_vec())?, expected);
453 Ok(())
454 }
455
456 #[test]
457 fn test_jsonb_to_string_escapes_object_keys()
458 -> std::result::Result<(), Box<dyn std::error::Error>> {
459 let expected = serde_json::json!({
460 "": 1,
461 "a\"b": {"c\\d": ["x", {"e\nf\tg\u{1}": true}], "h": null},
462 "plain": "v\"q",
463 });
464 let input = expected.to_string();
465 let value = jsonb::parse_value(input.as_bytes()).map_err(|e| e.to_string())?;
466 let text = jsonb_to_string(&value.to_vec())?;
467 assert_eq!(serde_json::from_str::<serde_json::Value>(&text)?, expected);
468 assert!(text.contains(r#""a\"b":"#), "{text}");
469 Ok(())
470 }
471
472 #[test]
473 fn test_jsonb_to_string_preserves_literal_unicode_escape_key() {
474 let input = r#"{"\\u{1f600}":"value"}"#;
475 let bytes = parse_string_to_jsonb(input).unwrap();
476 let text = jsonb_to_string(&bytes).unwrap();
477 assert_eq!(
478 serde_json::from_str::<serde_json::Value>(&text).unwrap(),
479 serde_json::from_str::<serde_json::Value>(input).unwrap(),
480 );
481
482 let input = r#"{"\\u{41}":"value"}"#;
484 let bytes = parse_string_to_jsonb(input).unwrap();
485 let text = jsonb_to_string(&bytes).unwrap();
486 assert_eq!(text, input);
487 }
488
489 #[test]
490 fn test_jsonb_to_string_escapes_string_values() {
491 for input in [
494 r#"{"k":"\\u{1f600}"}"#,
495 r#"{"k":"\\u{41}"}"#,
496 r#"{"k":"a\u0000b"}"#,
497 r#"["\\u{1f600}","\u0000"]"#,
498 ] {
499 let bytes = parse_string_to_jsonb(input).unwrap();
500 let text = jsonb_to_string(&bytes).unwrap();
501 assert_eq!(
502 serde_json::from_str::<serde_json::Value>(&text).unwrap(),
503 serde_json::from_str::<serde_json::Value>(input).unwrap(),
504 "{input} -> {text}"
505 );
506 }
507
508 let bytes = parse_string_to_jsonb("{\"k\":\"a\\u2028b\"}").unwrap();
510 assert_eq!(jsonb_to_string(&bytes).unwrap(), "{\"k\":\"a\u{2028}b\"}");
511 }
512
513 #[test]
514 fn test_jsonb_to_string_rejects_invalid_jsonb() {
515 assert!(jsonb_to_string(&[1, 2, 3, 4]).is_err());
516 assert_eq!(jsonb_to_string(&[]).unwrap(), "");
517 }
518
519 #[test]
520 fn test_jsonb_to_string_accepts_json_text_bytes() {
521 assert_eq!(
523 jsonb_to_string(br#"{"foo":"bar"}"#).unwrap(),
524 r#"{"foo":"bar"}"#
525 );
526 assert_eq!(
527 jsonb_to_string(br#"{"a":null, "foo":"bar"}"#).unwrap(),
528 r#"{"a":null,"foo":"bar"}"#
529 );
530 assert_eq!(
532 jsonb_to_string(br#"{"a\"b":"c\u0000d"}"#).unwrap(),
533 r#"{"a\"b":"c\u0000d"}"#
534 );
535 assert!(jsonb_to_string(b"{not json").is_err());
536 }
537
538 #[test]
539 fn test_jsonb_to_string_keeps_compact_format() -> Result<()> {
540 let value = jsonb::parse_value(br#"{"b": [1, 2.5, "x"], "a": {"c": false}}"#).unwrap();
541 assert_eq!(
542 jsonb_to_string(&value.to_vec())?,
543 r#"{"a":{"c":false},"b":[1,2.5,"x"]}"#
544 );
545 Ok(())
546 }
547
548 use super::*;
549
550 #[test]
551 fn test_json_type_include() {
552 fn test(this: &JsonNativeType, that: &JsonNativeType, expected: bool) {
553 assert_eq!(is_include(this, that), expected, "this={this}, that={that}");
554 }
555
556 test(&JsonNativeType::Null, &JsonNativeType::Null, true);
557 test(&JsonNativeType::Null, &JsonNativeType::Bool, false);
558 test(&JsonNativeType::Bool, &JsonNativeType::Null, true);
559
560 test(&JsonNativeType::Bool, &JsonNativeType::Bool, true);
561 test(&JsonNativeType::Bool, &JsonNativeType::u64(), false);
562
563 test(&JsonNativeType::u64(), &JsonNativeType::Null, true);
564 test(&JsonNativeType::u64(), &JsonNativeType::u64(), true);
565 test(&JsonNativeType::u64(), &JsonNativeType::String, false);
566
567 test(&JsonNativeType::String, &JsonNativeType::Null, true);
568 test(&JsonNativeType::String, &JsonNativeType::String, true);
569 test(
570 &JsonNativeType::String,
571 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
572 false,
573 );
574
575 test(
576 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
577 &JsonNativeType::Null,
578 true,
579 );
580 test(
581 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
582 &JsonNativeType::Array(Box::new(JsonNativeType::Null)),
583 true,
584 );
585 test(
586 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
587 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
588 true,
589 );
590 test(
591 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
592 &JsonNativeType::String,
593 false,
594 );
595 test(
596 &JsonNativeType::Array(Box::new(JsonNativeType::f64())),
597 &JsonNativeType::Object(JsonObjectType::new()),
598 false,
599 );
600
601 let simple_json_object = &JsonNativeType::Object(JsonObjectType::from([(
602 "foo".to_string(),
603 JsonNativeType::String,
604 )]));
605 test(simple_json_object, simple_json_object, true);
606 test(simple_json_object, &JsonNativeType::i64(), false);
607 test(
608 simple_json_object,
609 &JsonNativeType::Object(JsonObjectType::from([(
610 "bar".to_string(),
611 JsonNativeType::i64(),
612 )])),
613 false,
614 );
615
616 let complex_json_object = &JsonNativeType::Object(JsonObjectType::from([
617 (
618 "nested".to_string(),
619 JsonNativeType::Object(JsonObjectType::from([(
620 "a".to_string(),
621 JsonNativeType::Object(JsonObjectType::from([(
622 "b".to_string(),
623 JsonNativeType::Object(JsonObjectType::from([(
624 "c".to_string(),
625 JsonNativeType::String,
626 )])),
627 )])),
628 )])),
629 ),
630 ("bar".to_string(), JsonNativeType::i64()),
631 ]));
632 test(simple_json_object, &JsonNativeType::Null, true);
633 test(complex_json_object, &JsonNativeType::String, false);
634 test(complex_json_object, complex_json_object, true);
635 test(
636 complex_json_object,
637 &JsonNativeType::Object(JsonObjectType::from([(
638 "bar".to_string(),
639 JsonNativeType::i64(),
640 )])),
641 true,
642 );
643 test(
644 complex_json_object,
645 &JsonNativeType::Object(JsonObjectType::from([
646 (
647 "nested".to_string(),
648 JsonNativeType::Object(JsonObjectType::from([(
649 "a".to_string(),
650 JsonNativeType::Null,
651 )])),
652 ),
653 ("bar".to_string(), JsonNativeType::i64()),
654 ])),
655 true,
656 );
657 test(
658 complex_json_object,
659 &JsonNativeType::Object(JsonObjectType::from([
660 (
661 "nested".to_string(),
662 JsonNativeType::Object(JsonObjectType::from([(
663 "a".to_string(),
664 JsonNativeType::String,
665 )])),
666 ),
667 ("bar".to_string(), JsonNativeType::i64()),
668 ])),
669 false,
670 );
671 test(
672 complex_json_object,
673 &JsonNativeType::Object(JsonObjectType::from([
674 (
675 "nested".to_string(),
676 JsonNativeType::Object(JsonObjectType::from([(
677 "a".to_string(),
678 JsonNativeType::Object(JsonObjectType::from([(
679 "b".to_string(),
680 JsonNativeType::String,
681 )])),
682 )])),
683 ),
684 ("bar".to_string(), JsonNativeType::i64()),
685 ])),
686 false,
687 );
688 test(
689 complex_json_object,
690 &JsonNativeType::Object(JsonObjectType::from([
691 (
692 "nested".to_string(),
693 JsonNativeType::Object(JsonObjectType::from([(
694 "a".to_string(),
695 JsonNativeType::Object(JsonObjectType::from([(
696 "b".to_string(),
697 JsonNativeType::Object(JsonObjectType::from([(
698 "c".to_string(),
699 JsonNativeType::Null,
700 )])),
701 )])),
702 )])),
703 ),
704 ("bar".to_string(), JsonNativeType::i64()),
705 ])),
706 true,
707 );
708 test(
709 complex_json_object,
710 &JsonNativeType::Object(JsonObjectType::from([
711 (
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::Bool,
720 )])),
721 )])),
722 )])),
723 ),
724 ("bar".to_string(), JsonNativeType::i64()),
725 ])),
726 false,
727 );
728 test(
729 complex_json_object,
730 &JsonNativeType::Object(JsonObjectType::from([(
731 "nested".to_string(),
732 JsonNativeType::Object(JsonObjectType::from([(
733 "a".to_string(),
734 JsonNativeType::Object(JsonObjectType::from([(
735 "b".to_string(),
736 JsonNativeType::Object(JsonObjectType::from([(
737 "c".to_string(),
738 JsonNativeType::String,
739 )])),
740 )])),
741 )])),
742 )])),
743 true,
744 );
745 }
746
747 #[test]
748 fn test_merge_json_type() {
749 fn test(other: JsonNativeType, json_type: &mut JsonNativeType, expected: &str) {
750 json_type.merge(&other);
751 assert_eq!(json_type.to_string(), expected);
752 }
753
754 test(
756 JsonNativeType::Bool,
757 &mut JsonNativeType::Null,
758 r#""<Bool>""#,
759 );
760
761 test(
763 JsonNativeType::Null,
764 &mut JsonNativeType::Bool,
765 r#""<Bool>""#,
766 );
767
768 test(
770 JsonNativeType::i64(),
771 &mut JsonNativeType::i64(),
772 r#""<Number>""#,
773 );
774
775 for (mut this, other) in [
777 (JsonNativeType::u64(), JsonNativeType::i64()),
778 (JsonNativeType::u64(), JsonNativeType::f64()),
779 (JsonNativeType::i64(), JsonNativeType::f64()),
780 ] {
781 test(other, &mut this, r#""<Variant>""#);
782 }
783
784 test(
786 JsonNativeType::Object(JsonObjectType::from([(
787 "foo".to_string(),
788 JsonNativeType::String,
789 )])),
790 &mut JsonNativeType::Object(JsonObjectType::from([(
791 "bar".to_string(),
792 JsonNativeType::i64(),
793 )])),
794 r#"{"bar":"<Number>","foo":"<String>"}"#,
795 );
796
797 test(
799 JsonNativeType::Object(JsonObjectType::from([(
800 "foo".to_string(),
801 JsonNativeType::i64(),
802 )])),
803 &mut JsonNativeType::Object(JsonObjectType::from([(
804 "foo".to_string(),
805 JsonNativeType::Bool,
806 )])),
807 r#"{"foo":"<Variant>"}"#,
808 );
809
810 test(
812 JsonNativeType::Object(JsonObjectType::from([(
813 "nested".to_string(),
814 JsonNativeType::Object(JsonObjectType::from([(
815 "foo".to_string(),
816 JsonNativeType::String,
817 )])),
818 )])),
819 &mut JsonNativeType::Object(JsonObjectType::from([(
820 "nested".to_string(),
821 JsonNativeType::Object(JsonObjectType::from([(
822 "bar".to_string(),
823 JsonNativeType::Bool,
824 )])),
825 )])),
826 r#"{"nested":{"bar":"<Bool>","foo":"<String>"}}"#,
827 );
828
829 test(
831 JsonNativeType::Array(Box::new(JsonNativeType::String)),
832 &mut JsonNativeType::Array(Box::new(JsonNativeType::u64())),
833 r#"["<Variant>"]"#,
834 );
835
836 test(
838 JsonNativeType::Object(JsonObjectType::from([(
839 "foo".to_string(),
840 JsonNativeType::String,
841 )])),
842 &mut JsonNativeType::Bool,
843 r#""<Variant>""#,
844 );
845 }
846}