pbjson_test/
lib.rs

1use serde::{Deserialize, Serialize};
2
3/// A test of an externally defined message
4#[derive(Clone, PartialEq, ::prost::Message, Serialize, Deserialize)]
5pub struct ExternMessage {}
6
7/// A test of an externally defined enumeration
8#[derive(
9    Clone,
10    Copy,
11    Debug,
12    PartialEq,
13    Eq,
14    Hash,
15    PartialOrd,
16    Ord,
17    ::prost::Enumeration,
18    Serialize,
19    Deserialize,
20)]
21#[repr(i32)]
22pub enum ExternEnumeration {
23    Unknown = 0,
24}
25
26pub mod test {
27    pub mod syntax3 {
28        include!(concat!(env!("OUT_DIR"), "/test.syntax3.rs"));
29        include!(concat!(env!("OUT_DIR"), "/test.syntax3.serde.rs"));
30    }
31
32    pub mod common {
33        include!(concat!(env!("OUT_DIR"), "/test.common.rs"));
34        include!(concat!(env!("OUT_DIR"), "/test.common.serde.rs"));
35    }
36
37    pub mod duplicate_name {
38        include!(concat!(env!("OUT_DIR"), "/test.duplicate_name.rs"));
39        include!(concat!(env!("OUT_DIR"), "/test.duplicate_name.serde.rs"));
40    }
41
42    pub mod duplicate_number {
43        include!(concat!(env!("OUT_DIR"), "/test.duplicate_number.rs"));
44        include!(concat!(env!("OUT_DIR"), "/test.duplicate_number.serde.rs"));
45    }
46
47    pub mod escape {
48        include!(concat!(
49            env!("OUT_DIR"),
50            "/test.r#abstract.r#type.escape.rs"
51        ));
52        include!(concat!(
53            env!("OUT_DIR"),
54            "/test.r#abstract.r#type.escape.serde.rs"
55        ));
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use std::error::Error;
62
63    use super::*;
64    use crate::test::syntax3::kitchen_sink::MixedCase;
65    use chrono::TimeZone;
66    use pbjson_types::{Duration, Timestamp};
67    use test::syntax3::*;
68
69    /// A struct holding the expected json-encoded representation of a test step.
70    ///
71    /// The json can come in two forms: fields with lowerCamelCase (typical expected) or with the
72    /// original name defined in the `.proto` schema. When decoding json, both forms must be
73    /// accepted by the parser. When encoding json, the form will be chosen based on the builder's
74    /// `preserve_proto_field_names` option, which during testing is toggled with a feature flag
75    #[derive(Debug, Clone, Copy)]
76    struct EncodedStrings {
77        expected: &'static str,
78
79        /// the proto-preserving encoding; None if equal to the standard encoding
80        expected_preserved_proto: Option<&'static str>,
81    }
82
83    impl From<&'static str> for EncodedStrings {
84        fn from(expected: &'static str) -> Self {
85            EncodedStrings {
86                expected,
87                expected_preserved_proto: None,
88            }
89        }
90    }
91
92    impl From<(&'static str, &'static str)> for EncodedStrings {
93        fn from((expected, expected_preserved_proto): (&'static str, &'static str)) -> Self {
94            EncodedStrings {
95                expected,
96                expected_preserved_proto: Some(expected_preserved_proto),
97            }
98        }
99    }
100
101    fn verify_encode(decoded: &KitchenSink, expected: impl Into<EncodedStrings>) {
102        let encoded = expected.into();
103
104        // the proto-preserved encoding is only used if the flag is set and the alternate form was
105        // actually provided
106        let expected = match (
107            cfg!(feature = "preserve-proto-field-names"),
108            encoded.expected_preserved_proto,
109        ) {
110            (true, Some(preserved_proto)) => preserved_proto,
111            _ => encoded.expected,
112        };
113
114        assert_eq!(serde_json::to_string(&decoded).unwrap().as_str(), expected);
115    }
116
117    fn verify_decode(decoded: &KitchenSink, expected: impl Into<EncodedStrings>) {
118        let encoded = expected.into();
119
120        // Decode from a string first
121        assert_eq!(decoded, &serde_json::from_str(encoded.expected).unwrap());
122
123        // Then, try decoding from a Reader: this can catch issues when trying to borrow data
124        // from the input, which is not possible when deserializing from a Reader (e.g. an opened
125        // file).
126        assert_eq!(
127            decoded,
128            &serde_json::from_reader(encoded.expected.as_bytes()).unwrap()
129        );
130
131        //both the lowerCamelCase and proto-preserved encodings must be accepted during decode
132        if let Some(expected_preserved_proto) = encoded.expected_preserved_proto {
133            assert_eq!(
134                decoded,
135                &serde_json::from_str(expected_preserved_proto).unwrap()
136            );
137            assert_eq!(
138                decoded,
139                &serde_json::from_reader(expected_preserved_proto.as_bytes()).unwrap()
140            );
141        }
142    }
143
144    fn verify_decode_err(encoded: &str, error: &str) {
145        let err = serde_json::from_str::<KitchenSink>(encoded)
146            .unwrap_err()
147            .to_string();
148
149        assert!(err.contains(error), "{}", err);
150    }
151
152    fn verify(decoded: &KitchenSink, expected: impl Into<EncodedStrings>) {
153        let expected = expected.into();
154        verify_encode(decoded, expected);
155        verify_decode(decoded, expected);
156    }
157
158    #[test]
159    #[cfg(not(feature = "ignore-unknown-fields"))]
160    fn test_unknown_field_error() {
161        let message = Empty {};
162
163        let encoded = serde_json::to_string(&message).unwrap();
164        let _decoded: Empty = serde_json::from_str(&encoded).unwrap();
165
166        let err = serde_json::from_str::<Empty>("343").unwrap_err();
167        assert_eq!(
168            err.to_string().as_str(),
169            "invalid type: integer `343`, expected struct test.syntax3.Empty at line 1 column 3"
170        );
171
172        let err = serde_json::from_str::<Empty>("{\"foo\": \"bar\"}").unwrap_err();
173        assert_eq!(
174            err.to_string().as_str(),
175            "unknown field `foo`, there are no fields at line 1 column 6"
176        );
177    }
178
179    #[test]
180    #[cfg(feature = "ignore-unknown-fields")]
181    fn test_ignore_unknown_field() {
182        let message = Empty {};
183
184        let encoded = serde_json::to_string(&message).unwrap();
185        let _decoded: Empty = serde_json::from_str(&encoded).unwrap();
186
187        let empty = serde_json::from_str::<Empty>("{\n \"foo\": \"bar\"\n}").unwrap();
188        assert_eq!(empty, Empty {});
189    }
190
191    #[test]
192    #[cfg(feature = "ignore-unknown-enum-variants")]
193    fn test_ignore_unknown_enum_variant() {
194        // A known string still maps correctly.
195        let kitchen_sink =
196            serde_json::from_str::<KitchenSink>("{\n \"value\": \"VALUE_A\"\n}").unwrap();
197        assert!(matches!(kitchen_sink, KitchenSink { value: 45, .. }));
198
199        // A known integer still maps correctly.
200        let kitchen_sink = serde_json::from_str::<KitchenSink>("{\n \"value\": 63\n}").unwrap();
201        assert!(matches!(kitchen_sink, KitchenSink { value: 63, .. }));
202
203        // An unknown string maps to default.
204        let kitchen_sink =
205            serde_json::from_str::<KitchenSink>("{\n \"value\": \"VALUE_DOES_NOT_EXIST\"\n}")
206                .unwrap();
207        assert!(matches!(kitchen_sink, KitchenSink { value: 0, .. }));
208
209        // An unknown integer maps to default.
210        let kitchen_sink = serde_json::from_str::<KitchenSink>("{\n \"value\": 1337\n}").unwrap();
211        assert!(matches!(kitchen_sink, KitchenSink { value: 0, .. }));
212
213        // Numeric values that don't fit in an i32 should still error.
214        assert!(serde_json::from_str::<KitchenSink>("{\n \"value\": 5.6\n}").is_err());
215        assert!(serde_json::from_str::<KitchenSink>("{\n \"value\": 3000000000\n}").is_err());
216    }
217
218    #[test]
219    #[cfg(feature = "btree")]
220    fn test_btree() {
221        use std::collections::BTreeMap;
222
223        let decoded = serde_json::from_str::<KitchenSink>("{}").unwrap();
224        assert_eq!(decoded.string_dict, BTreeMap::new());
225    }
226
227    #[test]
228    #[cfg(feature = "emit-fields")]
229    fn test_emit_fields() {
230        let mut decoded: KitchenSink = serde_json::from_str("{}").unwrap();
231        assert_ne!(serde_json::to_string(&decoded).unwrap().as_str(), "{}");
232    }
233
234    #[test]
235    #[cfg(all(not(feature = "emit-fields"), feature = "use-integers-for-enums"))]
236    fn test_use_integers_for_enums() {
237        let mut decoded: KitchenSink = serde_json::from_str("{}").unwrap();
238        assert_eq!(serde_json::to_string(&decoded).unwrap().as_str(), "{}");
239        decoded.value = kitchen_sink::Value::A as i32;
240        verify(&decoded, r#"{"value":45}"#);
241    }
242
243    #[test]
244    #[cfg(not(any(feature = "emit-fields", feature = "use-integers-for-enums")))]
245    fn test_kitchen_sink() {
246        let mut decoded: KitchenSink = serde_json::from_str("{}").unwrap();
247
248        verify(&decoded, "{}");
249        decoded.i32 = 24;
250        verify(&decoded, r#"{"i32":24}"#);
251        decoded.i32 = 0;
252        verify_decode(&decoded, "{}");
253
254        // Explicit optional fields can distinguish between no value and default value
255        decoded.optional_i32 = Some(2);
256        verify(&decoded, (r#"{"optionalI32":2}"#, r#"{"optional_i32":2}"#));
257
258        decoded.optional_i32 = Some(0);
259        verify(&decoded, (r#"{"optionalI32":0}"#, r#"{"optional_i32":0}"#));
260
261        // Can also decode from string
262        verify_decode(
263            &decoded,
264            (r#"{"optionalI32":"0"}"#, r#"{"optional_i32":"0"}"#),
265        );
266
267        decoded.optional_i32 = None;
268        verify_decode(&decoded, "{}");
269
270        // 64-bit integers are encoded as strings
271        decoded.i64 = 123125;
272        verify(&decoded, r#"{"i64":"123125"}"#);
273
274        decoded.i64 = 0;
275        verify_decode(&decoded, "{}");
276
277        decoded.optional_i64 = Some(532);
278        verify(
279            &decoded,
280            (r#"{"optionalI64":"532"}"#, r#"{"optional_i64":"532"}"#),
281        );
282
283        decoded.optional_i64 = Some(0);
284        verify(
285            &decoded,
286            (r#"{"optionalI64":"0"}"#, r#"{"optional_i64":"0"}"#),
287        );
288
289        // Can also decode from non-string
290        verify_decode(&decoded, (r#"{"optionalI64":0}"#, r#"{"optional_i64":0}"#));
291
292        decoded.optional_i64 = None;
293        verify_decode(&decoded, "{}");
294
295        decoded.u64 = 34346;
296        decoded.u32 = 567094456;
297        decoded.optional_u32 = Some(0);
298        decoded.optional_u64 = Some(3);
299        verify(
300            &decoded,
301            (
302                r#"{"u32":567094456,"optionalU32":0,"u64":"34346","optionalU64":"3"}"#,
303                r#"{"u32":567094456,"optional_u32":0,"u64":"34346","optional_u64":"3"}"#,
304            ),
305        );
306
307        decoded.u64 = 0;
308        decoded.u32 = 0;
309        decoded.optional_u32 = None;
310        decoded.optional_u64 = None;
311        verify_decode(&decoded, "{}");
312
313        decoded.repeated_i32 = vec![0, 23, 5, 6, 2, 34];
314        verify(
315            &decoded,
316            (
317                r#"{"repeatedI32":[0,23,5,6,2,34]}"#,
318                r#"{"repeated_i32":[0,23,5,6,2,34]}"#,
319            ),
320        );
321        // Can also mix in some strings
322        verify_decode(
323            &decoded,
324            (
325                r#"{"repeatedI32":[0,"23",5,6,"2",34]}"#,
326                r#"{"repeated_i32":[0,"23",5,6,"2",34]}"#,
327            ),
328        );
329
330        decoded.repeated_i32 = vec![];
331        verify_decode(&decoded, "{}");
332
333        decoded.repeated_u64 = vec![0, 532, 2];
334        verify(
335            &decoded,
336            (
337                r#"{"repeatedU64":["0","532","2"]}"#,
338                r#"{"repeated_u64":["0","532","2"]}"#,
339            ),
340        );
341        // Can also mix in some non-strings
342        verify_decode(
343            &decoded,
344            (
345                r#"{"repeatedU64":["0",532,"2"]}"#,
346                r#"{"repeated_u64":["0",532,"2"]}"#,
347            ),
348        );
349
350        decoded.repeated_u64 = vec![];
351        verify_decode(&decoded, "{}");
352
353        // Enumerations should be encoded as strings
354        decoded.value = kitchen_sink::Value::A as i32;
355        verify(&decoded, r#"{"value":"VALUE_A"}"#);
356
357        // Can also use variant number
358        verify_decode(&decoded, r#"{"value":45}"#);
359
360        decoded.value = kitchen_sink::Value::Unknown as i32;
361        verify_decode(&decoded, "{}");
362
363        decoded.optional_value = Some(kitchen_sink::Value::Unknown as i32);
364        verify(
365            &decoded,
366            (
367                r#"{"optionalValue":"VALUE_UNKNOWN"}"#,
368                r#"{"optional_value":"VALUE_UNKNOWN"}"#,
369            ),
370        );
371
372        // Can also use variant number
373        verify_decode(
374            &decoded,
375            (r#"{"optionalValue":0}"#, r#"{"optional_value":0}"#),
376        );
377
378        decoded.optional_value = None;
379        verify_decode(&decoded, "{}");
380
381        decoded
382            .string_dict
383            .insert("foo".to_string(), "bar".to_string());
384        verify(
385            &decoded,
386            (
387                r#"{"stringDict":{"foo":"bar"}}"#,
388                r#"{"string_dict":{"foo":"bar"}}"#,
389            ),
390        );
391
392        decoded.string_dict = Default::default();
393        verify_decode(&decoded, "{}");
394
395        decoded
396            .int32_dict
397            .insert(343, kitchen_sink::Prefix::A as i32);
398        // Dictionary keys should always be strings
399        // Enum dictionary values should be encoded as strings
400        verify(
401            &decoded,
402            (
403                r#"{"int32Dict":{"343":"A"}}"#,
404                r#"{"int32_dict":{"343":"A"}}"#,
405            ),
406        );
407        // Enum dictionary values can be decoded from integers
408        verify_decode(
409            &decoded,
410            (
411                r#"{"int32Dict":{"343":66}}"#,
412                r#"{"int32_dict":{"343":66}}"#,
413            ),
414        );
415
416        decoded.int32_dict = Default::default();
417        verify_decode(&decoded, "{}");
418
419        // 64-bit dictionary values should be encoded as strings
420        decoded.integer_dict.insert(12, 13);
421        verify(
422            &decoded,
423            (
424                r#"{"integerDict":{"12":"13"}}"#,
425                r#"{"integer_dict":{"12":"13"}}"#,
426            ),
427        );
428        // 64-bit dictionary values can be decoded from numeric types
429        verify_decode(
430            &decoded,
431            (
432                r#"{"integerDict":{"12":13}}"#,
433                r#"{"integer_dict":{"12":13}}"#,
434            ),
435        );
436
437        decoded.integer_dict = Default::default();
438        verify_decode(&decoded, "{}");
439
440        decoded.one_of = Some(kitchen_sink::OneOf::OneOfI32(0));
441        verify(&decoded, (r#"{"oneOfI32":0}"#, r#"{"one_of_i32":0}"#));
442        // Can also specify string
443        verify_decode(&decoded, (r#"{"oneOfI32":"0"}"#, r#"{"one_of_i32":"0"}"#));
444
445        decoded.one_of = Some(kitchen_sink::OneOf::OneOfI32(12));
446        verify(&decoded, (r#"{"oneOfI32":12}"#, r#"{"one_of_i32":12}"#));
447
448        decoded.one_of = Some(kitchen_sink::OneOf::OneOfBool(false));
449        verify(
450            &decoded,
451            (r#"{"oneOfBool":false}"#, r#"{"one_of_bool":false}"#),
452        );
453
454        decoded.one_of = Some(kitchen_sink::OneOf::OneOfBool(true));
455        verify(
456            &decoded,
457            (r#"{"oneOfBool":true}"#, r#"{"one_of_bool":true}"#),
458        );
459
460        decoded.one_of = Some(kitchen_sink::OneOf::OneOfValue(
461            kitchen_sink::Value::B as i32,
462        ));
463        verify(
464            &decoded,
465            (
466                r#"{"oneOfValue":"VALUE_B"}"#,
467                r#"{"one_of_value":"VALUE_B"}"#,
468            ),
469        );
470        // Can also specify enum variant
471        verify_decode(&decoded, (r#"{"oneOfValue":63}"#, r#"{"one_of_value":63}"#));
472
473        decoded.one_of = None;
474        verify_decode(&decoded, "{}");
475
476        decoded.repeated_value = vec![
477            kitchen_sink::Value::B as i32,
478            kitchen_sink::Value::B as i32,
479            kitchen_sink::Value::A as i32,
480        ];
481        verify(
482            &decoded,
483            (
484                r#"{"repeatedValue":["VALUE_B","VALUE_B","VALUE_A"]}"#,
485                r#"{"repeated_value":["VALUE_B","VALUE_B","VALUE_A"]}"#,
486            ),
487        );
488        verify_decode(
489            &decoded,
490            (
491                r#"{"repeatedValue":[63,"VALUE_B","VALUE_A"]}"#,
492                r#"{"repeated_value":[63,"VALUE_B","VALUE_A"]}"#,
493            ),
494        );
495
496        decoded.repeated_value = Default::default();
497        verify_decode(&decoded, "{}");
498
499        decoded.bytes = prost::bytes::Bytes::from_static(b"kjkjkj");
500        verify(&decoded, r#"{"bytes":"a2pramtq"}"#);
501
502        decoded.bytes = Default::default();
503        verify_decode(&decoded, "{}");
504
505        decoded.optional_bytes = Some(prost::bytes::Bytes::from_static(b"kjkjkj"));
506        verify(
507            &decoded,
508            (
509                r#"{"optionalBytes":"a2pramtq"}"#,
510                r#"{"optional_bytes":"a2pramtq"}"#,
511            ),
512        );
513
514        decoded.optional_bytes = Some(Default::default());
515        verify(
516            &decoded,
517            (r#"{"optionalBytes":""}"#, r#"{"optional_bytes":""}"#),
518        );
519
520        decoded.optional_bytes = None;
521        verify_decode(&decoded, "{}");
522
523        decoded.repeated_bytes = vec![
524            prost::bytes::Bytes::from_static(b"sdfsd"),
525            prost::bytes::Bytes::from_static(b"fghfg"),
526        ];
527        verify(
528            &decoded,
529            (
530                r#"{"repeatedBytes":["c2Rmc2Q=","ZmdoZmc="]}"#,
531                r#"{"repeated_bytes":["c2Rmc2Q=","ZmdoZmc="]}"#,
532            ),
533        );
534
535        decoded.repeated_bytes = Default::default();
536        verify_decode(&decoded, "{}");
537
538        decoded.string_bytes_dict.insert(
539            "test".to_string(),
540            prost::bytes::Bytes::from_static(b"asdf"),
541        );
542        verify(
543            &decoded,
544            (
545                r#"{"stringBytesDict":{"test":"YXNkZg=="}}"#,
546                r#"{"string_bytes_dict":{"test":"YXNkZg=="}}"#,
547            ),
548        );
549
550        decoded.string_bytes_dict = Default::default();
551        verify_decode(&decoded, "{}");
552
553        decoded
554            .int_bytes_dict
555            .insert(43, prost::bytes::Bytes::from_static(b"343dfgd"));
556        verify(
557            &decoded,
558            (
559                r#"{"intBytesDict":{"43":"MzQzZGZnZA=="}}"#,
560                r#"{"int_bytes_dict":{"43":"MzQzZGZnZA=="}}"#,
561            ),
562        );
563
564        decoded.int_bytes_dict = Default::default();
565        verify_decode(&decoded, "{}");
566
567        decoded.string = "test".to_string();
568        verify(&decoded, r#"{"string":"test"}"#);
569
570        decoded.string = Default::default();
571        verify_decode(&decoded, "{}");
572
573        decoded.optional_string = Some(String::new());
574        verify(
575            &decoded,
576            (r#"{"optionalString":""}"#, r#"{"optional_string":""}"#),
577        );
578
579        decoded.optional_string = None;
580        verify_decode(&decoded, "{}");
581
582        let date = chrono::Utc
583            .with_ymd_and_hms(2072, 3, 1, 5, 2, 5)
584            .unwrap()
585            .checked_add_signed(chrono::Duration::milliseconds(30))
586            .unwrap();
587        decoded.timestamp = Some(Timestamp {
588            seconds: date.timestamp(),
589            nanos: date.timestamp_subsec_nanos() as i32,
590        });
591
592        verify(&decoded, r#"{"timestamp":"2072-03-01T05:02:05.030+00:00"}"#);
593
594        decoded.timestamp = None;
595        verify_decode(&decoded, "{}");
596
597        decoded.duration = Some(Duration {
598            seconds: 40502002,
599            nanos: 5049,
600        });
601        verify(&decoded, r#"{"duration":"40502002.000005049s"}"#);
602
603        decoded.duration = None;
604        verify_decode(&decoded, "{}");
605
606        decoded.mixed_case = MixedCase::MixedCasea as _;
607        verify(
608            &decoded,
609            (
610                r#"{"mixedCase":"MixedCASEA"}"#,
611                r#"{"mixed_case":"MixedCASEA"}"#,
612            ),
613        );
614
615        decoded.mixed_case = MixedCase::MixEdCaseB as _;
616        verify(
617            &decoded,
618            (
619                r#"{"mixedCase":"MixEdCaseB"}"#,
620                r#"{"mixed_case":"MixEdCaseB"}"#,
621            ),
622        );
623
624        decoded.mixed_case = MixedCase::C as _;
625        verify(&decoded, (r#"{"mixedCase":"c"}"#, r#"{"mixed_case":"c"}"#));
626
627        decoded.mixed_case = MixedCase::Unknown as _;
628        verify(&decoded, r#"{}"#);
629
630        decoded.bool_value = Some(true.into());
631        verify(
632            &decoded,
633            (r#"{"boolValue":true}"#, r#"{"bool_value":true}"#),
634        );
635
636        decoded.bool_value = Some(false.into());
637        verify(
638            &decoded,
639            (r#"{"boolValue":false}"#, r#"{"bool_value":false}"#),
640        );
641
642        decoded.bool_value = None;
643        verify(&decoded, r#"{}"#);
644
645        decoded.bytes_value = Some(prost::bytes::Bytes::from_static(b"kjkjkj").into());
646        verify(
647            &decoded,
648            (
649                r#"{"bytesValue":"a2pramtq"}"#,
650                r#"{"bytes_value":"a2pramtq"}"#,
651            ),
652        );
653
654        decoded.bytes_value = Some(prost::bytes::Bytes::new().into());
655        verify(&decoded, (r#"{"bytesValue":""}"#, r#"{"bytes_value":""}"#));
656
657        decoded.bytes_value = None;
658        verify(&decoded, r#"{}"#);
659
660        decoded.double_value = Some(1.1.into());
661        verify(
662            &decoded,
663            (r#"{"doubleValue":1.1}"#, r#"{"double_value":1.1}"#),
664        );
665
666        decoded.double_value = Some(0.0.into());
667        verify(
668            &decoded,
669            (r#"{"doubleValue":0.0}"#, r#"{"double_value":0.0}"#),
670        );
671
672        decoded.double_value = None;
673        verify(&decoded, r#"{}"#);
674
675        decoded.uint32_value = Some(1.into());
676        verify(&decoded, (r#"{"uint32Value":1}"#, r#"{"uint32_value":1}"#));
677
678        decoded.uint32_value = Some(0.into());
679        verify(&decoded, (r#"{"uint32Value":0}"#, r#"{"uint32_value":0}"#));
680
681        decoded.uint32_value = None;
682        verify(&decoded, r#"{}"#);
683
684        decoded.uint64_value = Some(1.into());
685        verify(
686            &decoded,
687            (r#"{"uint64Value":"1"}"#, r#"{"uint64_value":"1"}"#),
688        );
689
690        decoded.uint64_value = Some(0.into());
691        verify(
692            &decoded,
693            (r#"{"uint64Value":"0"}"#, r#"{"uint64_value":"0"}"#),
694        );
695
696        decoded.uint64_value = None;
697        verify(&decoded, r#"{}"#);
698
699        decoded.string_value = Some(String::from("1").into());
700        verify(
701            &decoded,
702            (r#"{"stringValue":"1"}"#, r#"{"string_value":"1"}"#),
703        );
704
705        decoded.string_value = Some(String::new().into());
706        verify(
707            &decoded,
708            (r#"{"stringValue":""}"#, r#"{"string_value":""}"#),
709        );
710
711        decoded.string_value = None;
712        verify(&decoded, r#"{}"#);
713
714        // Test explicit null optional scalar
715        verify_decode(&decoded, r#"{"optionalU32":null}"#);
716        verify_decode(&decoded, r#"{"optionalU64":null}"#);
717        verify_decode(&decoded, r#"{"optionalString":null}"#);
718
719        // Test explicit null optional enum
720        verify_decode(&decoded, r#"{"optionalValue":null}"#);
721
722        // Test explicit null message
723        verify_decode(&decoded, r#"{"empty":null}"#);
724
725        // Test explicit null in oneof
726        verify_decode(&decoded, r#"{"oneOfI32":null}"#);
727        verify_decode(&decoded, r#"{"oneOfBool":null}"#);
728        verify_decode(&decoded, r#"{"oneOfValue":null}"#);
729        verify_decode(&decoded, r#"{"oneOfMessage":null}"#);
730
731        // Test explicit null value type
732        verify_decode(&decoded, r#"{"boolValue":null}"#);
733        verify_decode(&decoded, r#"{"bytesValue":null}"#);
734        verify_decode(&decoded, r#"{"doubleValue":null}"#);
735        verify_decode(&decoded, r#"{"floatValue":null}"#);
736        verify_decode(&decoded, r#"{"int32Value":null}"#);
737        verify_decode(&decoded, r#"{"int64Value":null}"#);
738        verify_decode(&decoded, r#"{"stringValue":null}"#);
739        verify_decode(&decoded, r#"{"uint32Value":null}"#);
740        verify_decode(&decoded, r#"{"uint64Value":null}"#);
741
742        // Test primitives are not nullable
743        verify_decode_err(r#"{"i32":null}"#, "data did not match any variant");
744        verify_decode_err(r#"{"u64":null}"#, "data did not match any variant");
745        verify_decode_err(r#"{"value":null}"#, "invalid type: null");
746        verify_decode_err(r#"{"bool":null}"#, "invalid type: null");
747        verify_decode_err(r#"{"string":null}"#, "invalid type: null");
748
749        // Test lists are not nullable
750        verify_decode_err(
751            r#"{"repeatedI32":null}"#,
752            "invalid type: null, expected a sequence",
753        );
754        verify_decode_err(
755            r#"{"repeatedI32":[null]}"#,
756            "data did not match any variant",
757        );
758        verify_decode_err(
759            r#"{"repeatedInt32Value":null}"#,
760            "invalid type: null, expected a sequence",
761        );
762        verify_decode_err(
763            r#"{"repeatedInt32Value":[null]}"#,
764            "data did not match any variant",
765        );
766
767        // Test maps are not nullable
768        verify_decode_err(
769            r#"{"stringDict":null}"#,
770            "invalid type: null, expected a map",
771        );
772        verify_decode_err(
773            r#"{"stringDict": {"foo": null}}"#,
774            "invalid type: null, expected a string ",
775        );
776        verify_decode_err(
777            r#"{"mapInt32Value":null}"#,
778            "invalid type: null, expected a map",
779        );
780        verify_decode_err(
781            r#"{"mapInt32Value":{"foo": null}}"#,
782            "data did not match any variant",
783        );
784    }
785
786    #[test]
787    fn test_escaped() -> Result<(), Box<dyn Error>> {
788        use super::test::escape::{Abstract, Target, Type};
789
790        let r#type = Type { example: true };
791        let r#abstract = Abstract {
792            r#type: Some(r#type),
793        };
794        let target = Target {
795            r#abstract: Some(r#abstract),
796        };
797
798        let encoded = serde_json::to_string(&target)?;
799
800        let expected = r#"{"abstract":{"type":{"example":true}}}"#;
801        assert_eq!(encoded, expected);
802
803        let decoded = serde_json::from_str::<Target>(&encoded)?;
804        assert_eq!(decoded, target);
805
806        Ok(())
807    }
808}