lil_json/
lib.rs

1#![no_std]
2
3use embedded_io::{ErrorType, Write};
4use numtoa::base10;
5
6/// terminal (non-nested) JSON types
7#[derive(Debug,PartialEq,Eq,Clone,Copy)]
8pub enum JsonValue<'a> {
9    /// a JSON string - it will be automatically escaped
10    String(&'a str),
11    /// a JSON boolean
12    Boolean(bool),
13    /// a JSON number
14    Number(i64),
15}
16
17/// a field within a JSON object
18#[derive(Debug,PartialEq,Eq,Clone,Copy)]
19pub struct JsonField<'a,'b> {
20    pub key: &'a str,
21    pub value: JsonValue<'b>,
22}
23
24impl <'a,'b> JsonField<'a,'b> {
25    /// create a new JSON object field with the given key & value
26    pub fn new(key: &'a str, value: JsonValue<'b>) -> Self {
27        JsonField { key, value }
28    }
29    /// convenience helper to create a new JSON object string field
30    pub fn new_string(key: &'a str, value: &'b str) -> Self {
31        Self::new(key, JsonValue::String(value))
32    }
33    /// convenience helper to create a new JSON object number field
34    pub fn new_number(key: &'a str, value: i64) -> Self {
35        Self::new(key, JsonValue::Number(value))
36    }
37    /// convenience helper to create a new JSON object boolean field
38    pub fn new_boolean(key: &'a str, value: bool) -> Self {
39        Self::new(key, JsonValue::Boolean(value))
40    }
41}
42
43/// a JSON Object (rfc8259) that wraps a mutable or immutable buffer of object fields. The easiest way to use it is through the ArrayJsonObject type alias, however you can use JsonObject directly to wrap your own buffer like a heap allocated Vec
44#[derive(Debug)]
45pub struct JsonObject<Fields> {
46    fields: Fields,
47    num_fields: usize,
48}
49
50/// the various reasons parsing JSON can fail
51#[derive(Debug)]
52pub enum JsonParseFailure {
53    /// there was no error, but the data slice is incomplete
54    Incomplete,
55    /// there was no error, but there were more fields than the provided field buffer could hold
56    TooManyFields,
57    /// there was an error in the JSON structure of the data
58    InvalidStructure,
59    /// an invalid JSON string was encountered
60    InvalidStringField,
61    /// an invalid JSON number was encountered
62    InvalidNumericField,
63    /// an invalid JSON boolean was encountered
64    InvalidBooleanField,
65}
66
67/// a default JSON field with static lifetime
68pub const EMPTY_FIELD: JsonField<'static,'static> = JsonField{ key: "", value: JsonValue::Number(0)};
69
70impl <'a,'b> Default for JsonField<'a,'b> {
71    fn default() -> Self {
72        EMPTY_FIELD
73    }
74}
75
76impl<T> JsonObject<T> {
77    /// consume this JsonObject to return (field buffer, num fields considered initialized)
78    pub fn into_inner(self) -> (T,usize) {
79        (self.fields,self.num_fields)
80    }
81}
82
83impl<'a,T: FieldBuffer<'a> + Default + ?Sized> Default for JsonObject<T> {
84    fn default() -> Self {
85        JsonObject { fields: T::default(), num_fields: 0 }
86    }
87}
88
89// trait for an optionally mutable collection of fields
90pub trait FieldBuffer<'data>: AsRef<[JsonField<'data,'data>]> {
91
92    /// convenience one-liner to call JsonObject::wrap_init on this Sized type, consuming it
93    fn into_json_object(self) -> JsonObject<Self> where Self: Sized {
94        JsonObject::wrap_init(self)
95    }
96    
97    /// convenience one-liner to call JsonObject::wrap_init on an immutable reference to this type
98    fn as_json_object(&self) -> JsonObject<&Self> {
99        JsonObject::wrap_init(self)
100    }
101
102}
103
104/// FieldBuffer is automatically implemented for all types that implement AsRef<[JsonField<'data,'data>]>
105impl <'a,T: AsRef<[JsonField<'a,'a>]>> FieldBuffer<'a> for T {}
106
107// trait for a  mutable collection of fields
108pub trait FieldBufferMut<'a>: FieldBuffer<'a> +  AsMut<[JsonField<'a,'a>]> {
109
110    /// convenience one-liner to call JsonObject::wrap_init on a mutable reference to this type
111    fn as_json_object_mut(&mut self) -> JsonObject<&mut Self> {
112        JsonObject::wrap_init(self)
113    }
114
115}
116
117/// FieldBufferMut is automatically implemented for all types that implement FieldBuffer + AsMut<[JsonField<'data,'data>]>
118impl <'a,T: FieldBuffer<'a> + AsMut<[JsonField<'a,'a>]>> FieldBufferMut<'a> for T {}
119
120pub trait StringWrite: ErrorType {
121    fn write_string(&mut self, data: &str) -> (usize,Result<(), <Self as ErrorType>::Error>);
122}
123
124impl<T: Write> StringWrite for T {
125    fn write_string(&mut self, mut data: &str) -> (usize,Result<(), <Self as ErrorType>::Error>) {
126        let mut written = 0_usize;
127        loop {
128            if data.is_empty() {
129                return (written,Ok(()));
130            }
131            let n = match self.write(data.as_bytes()) {
132                Ok(0) => panic!(),
133                Err(e) => return (written, Err(e)),
134                Ok(n) => n,
135            };
136            written += n;
137            data = data.split_at(n).1
138        }
139    }
140}
141
142/// (re-export from embedded-io-adapters)
143
144// TODO: alloc almost done
145// impl <'a,T: FieldBuffer<'a>> ToString for JsonObject<T> {
146//     fn to_string(&self) -> String {
147//         self.serialize_into(output)
148//     }
149// }
150
151
152impl <'a,T: FieldBuffer<'a>> JsonObject<T> {
153
154    /// wrap a collection of fields into a JsonObject and considers none of the fields to be initialized
155    pub const fn wrap(fields: T) -> Self {
156        JsonObject { fields, num_fields: 0 }
157    }
158
159    /// wrap a collection of fields into a JsonObject and considers all of the fields to be initialized
160    pub fn wrap_init(fields: T) -> Self {
161        let num_fields = fields.as_ref().len();
162        JsonObject { fields, num_fields }
163    }
164
165    /// get the number of initialized fields in this JsonObject. Same as self.fields().len().
166    pub const fn len(&self) -> usize {
167        self.num_fields
168    }
169
170    /// get the max number of fields this JsonObject can store.
171    pub fn capacity(&self) -> usize {
172        self.fields.as_ref().len()
173    }
174
175    /// get an immutable reference to the initialized fields of this JsonObject
176    pub fn fields(&self) -> &[JsonField<'a,'a>] {
177        self.fields.as_ref().split_at(self.num_fields).0
178    }
179
180
181
182    // #[cfg(feature = "std")]
183    // pub fn serialize_to_stdout(&self) -> Result<usize,std::StandardLibIoError> {
184    //     use std::StdIoAdapter;
185
186    //     self.serialize_into(StdIoAdapter::new())
187    // }
188
189    // #[cfg(feature = "std")]
190    // pub fn serialize_to_stderr(&self) -> Result<usize,std::S> {
191    //     use embedded_io_adapters::std::FromStd;
192    //     self.serialize_into(FromStd::new(stdlib::io::stderr()))
193    // }
194
195    /// attempt to serialize this JsonObject into the provided output, returns the number of bytes written on success
196    pub fn serialize_into<Output: Write>(&self, output: Output) -> Result<usize,Output::Error> {
197        serialize_json_object(output, self.fields().as_ref())
198    }
199}
200
201impl<'a,T: FieldBuffer<'a>> From<T> for JsonObject<T> {
202    fn from(field_buffer: T) -> Self {
203        JsonObject::wrap_init(field_buffer)
204    }
205}
206
207impl <'a,T: FieldBufferMut<'a>> JsonObject<T> {
208
209    /// get a mutable reference to the initialized fields of this JsonObject
210    pub fn fields_mut(&mut self) -> &mut [JsonField<'a,'a>] {
211        self.fields.as_mut().split_at_mut(self.num_fields).0
212    }
213
214    /// attempt to push a new field - returns the field if there is not enough space
215    pub fn push<'x: 'a,'y: 'a>(&mut self, field: JsonField<'x,'y>) -> Result<(),JsonField<'x,'y>> {
216        if self.num_fields == self.fields.as_ref().len(){
217            return Err(field);
218        }
219        self.fields.as_mut()[self.num_fields] = field;
220        self.num_fields += 1;
221        Ok(())
222    }
223
224    /// attempt to pop an existing field - returns None if there are no initialized fields
225    pub fn pop(&mut self) -> Option<JsonField<'a,'a>> {
226        if self.num_fields == 0 {
227            return None;
228        }
229        self.num_fields -= 1;
230        Some(core::mem::take(&mut self.fields.as_mut()[self.num_fields+1]))
231    }
232
233    /// convenience helper to create and push a new field
234    pub fn push_field<'x: 'a,'y: 'a>(&mut self, key: &'x str, value: JsonValue<'y>) -> Result<(),()> {
235        if self.num_fields == self.fields.as_ref().len(){
236            return Err(());
237        }
238        self.fields.as_mut()[self.num_fields] = JsonField { key, value };
239        self.num_fields += 1;
240        Ok(())
241    }
242
243    /// attempt to parse a JSON object from the provided data slice and write its fields into this JsonObject - returns a tuple of (num bytes consumed, num fields parsed) on success
244    pub fn parse(&mut self, data: &'a [u8]) -> Result<(usize,usize),JsonParseFailure> {
245        let (data_end, parsed_fields) = parse_json_object(data, self.fields.as_mut())?;
246        let new_num_fields = parsed_fields.len();
247        self.num_fields = new_num_fields;
248        Ok((data_end,new_num_fields))
249    }
250
251}
252
253impl <'a,T: FieldBufferMut<'a> + Default> JsonObject<T> {
254
255    /// convenience method to automatically create an JsonObject if object parsing is successful
256    pub fn default_parsed(data: &'a [u8]) -> Result<(usize,Self),JsonParseFailure> {
257        let mut ret = Self::default();
258        let (num_bytes,_num_fields) = ret.parse(data)?;
259        Ok((num_bytes,ret))
260    }
261
262}
263
264
265/// ArrayJsonObject is a type alias for a JsonObject that wraps an array. It is has some additional functionality compared to a normal JsonObject.
266pub type ArrayJsonObject<'a,const N: usize> = JsonObject<[JsonField<'a,'a>; N]>;
267
268impl<'a,const N: usize> ArrayJsonObject<'a,N> {
269
270    /// convenience method to call JsonObject::wrap on a new array
271    pub const fn new() -> Self {
272        JsonObject::wrap([EMPTY_FIELD; N])
273    }
274
275    /// convenience method to automatically create an ArrayJsonObject if object parsing is successful
276    pub fn new_parsed(data: &'a [u8]) -> Result<(usize,Self),JsonParseFailure> {
277        let mut ret = Self::new();
278        let (data_end,_num_headers) = ret.parse(data)?;
279        Ok((data_end,ret))
280    }
281
282    /// similar to JsonObject::push but supports const contexts & only returns a reference
283    pub const fn push_const(&mut self, key: &'a str, value: JsonValue<'a>) -> Result<(),()> {
284        if self.num_fields == N {
285            return Err(());
286        }
287        self.fields[self.num_fields] = JsonField { key, value: value };
288        self.num_fields += 1;
289        Ok(())
290    }
291
292    /// similar to JsonObject::pop but supports const contexts
293    pub const fn pop_const(&mut self) -> Option<&JsonField<'a,'a>> {
294        match self.fields_const().split_last() {
295            None => return None,
296            Some((split,_remaining)) => return Some(split),
297        }
298    }
299
300    /// same as JsonObject::fields but supports const contexts
301    pub const fn fields_const(&self) -> &[JsonField<'a,'a>] {
302        self.fields.split_at(self.num_fields).0
303    }
304
305    /// same as JsonObject::fields_mut but supports const contexts
306    pub const fn fields_mut_const(&mut self) -> &mut [JsonField<'a,'a>] {
307        self.fields.split_at_mut(self.num_fields).0
308    }
309
310}
311
312/// the core function that powers parsing in the JsonObject API. It attempts to parse the fields of a json object from the provided data slice into the provided field buffer, then return (data bytes consumed, parsed field slice) on success.
313pub fn parse_json_object<'data,'field_buffer>(data: &'data [u8], field_buffer: &'field_buffer mut [JsonField<'data,'data>]) -> Result<(usize,&'field_buffer[JsonField<'data,'data>]),JsonParseFailure> {
314    let mut current_data_index = 0;
315    let mut current_field_index = 0;
316    let mut map_entry_needs_comma = false;
317    skip_whitespace(&mut current_data_index, data)?;
318    if data[current_data_index] != b'{' {
319        return Err(JsonParseFailure::InvalidStructure);
320    }
321    let _map_start_index = current_data_index;
322    current_data_index += 1;
323    while current_data_index < data.len()  {
324        skip_whitespace(&mut current_data_index, data)?;
325        if data[current_data_index] == b'}' {
326            return Ok((current_data_index+1,field_buffer.split_at(current_field_index).0))
327        } else if map_entry_needs_comma  {
328            if data[current_data_index] != b',' {
329                return Err(JsonParseFailure::InvalidStructure);
330            }
331            current_data_index += 1;
332            map_entry_needs_comma = false;
333        } else {
334            map_entry_needs_comma = true;
335            let key_start_quote_index = current_data_index;
336            current_data_index += 1;
337            skip_json_string(&mut current_data_index, data)?;
338            let key_end_quote_index = current_data_index;
339            let string_key = core::str::from_utf8(&data[key_start_quote_index+1..key_end_quote_index]).expect("skipped json object key string");
340            current_data_index += 1;
341            skip_whitespace(&mut current_data_index, data)?;
342            if data[current_data_index] != b':' {
343                return Err(JsonParseFailure::InvalidStructure);
344            }
345            current_data_index += 1;
346            skip_whitespace(&mut current_data_index, data)?;
347
348            if data[current_data_index] == b'"' {
349                let value_start_quote_index = current_data_index;
350                current_data_index += 1;
351                skip_json_string(&mut current_data_index, data)?;
352                let value_end_quote_index = current_data_index;
353                current_data_index += 1;
354                let string_value = core::str::from_utf8(&data[value_start_quote_index+1..value_end_quote_index]).expect("skipped json object value string");
355                if current_field_index >= field_buffer.len() {
356                    return Err(JsonParseFailure::TooManyFields);
357                }
358                field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::String(string_value));
359                current_field_index += 1;
360            } else if data[current_data_index] == b't' || data[current_data_index] == b'f' {
361                let expect_true = data[current_data_index] == b't';
362                skip_json_boolean(&mut current_data_index, data, expect_true)?;
363                if current_field_index >= field_buffer.len() {
364                    return Err(JsonParseFailure::TooManyFields);
365                }
366                field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::Boolean(expect_true));
367                current_field_index += 1;
368            } else if (data[current_data_index] >= b'0' && data[current_data_index] < b'9') || data[current_data_index] == b'-' {
369                let numeric_start_index = current_data_index;
370                current_data_index += 1;
371                skip_json_numeric(&mut current_data_index, data)?;
372                let numeric_after_index = current_data_index;
373                let numeric_string = core::str::from_utf8(&data[numeric_start_index..numeric_after_index]).expect("skipped numeric digits");
374                let numeric_value: i64 = match numeric_string.parse() {
375                    Ok(i) => i,
376                    Err(_) => return Err(JsonParseFailure::InvalidNumericField),
377                };
378                if current_field_index >= field_buffer.len() {
379                    return Err(JsonParseFailure::TooManyFields);
380                }
381                field_buffer[current_field_index] = JsonField::new(string_key, JsonValue::Number(numeric_value));
382                current_field_index += 1;
383            } else {
384                return Err(JsonParseFailure::InvalidStructure);
385            }
386        }
387    }
388    Err(JsonParseFailure::Incomplete)
389}
390
391fn skip_json_string(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
392    let mut last_char_escape = false;
393    while *index < data.len() {
394        if data[*index] == b'\\' && !last_char_escape {
395            last_char_escape = true;
396        } else if data[*index] == b'"' && !last_char_escape {
397            return Ok(());
398        } else if !data[*index].is_ascii() {
399            return Err(JsonParseFailure::InvalidStringField);
400        } else {
401            last_char_escape = false
402        }
403        *index += 1;
404    }
405    Err(JsonParseFailure::Incomplete)
406}
407
408fn skip_json_numeric(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
409    while *index < data.len() && data[*index] <= b'9' && data[*index] >= b'0' {
410        *index += 1;
411    }
412    if *index == data.len() {
413        Err(JsonParseFailure::Incomplete)
414    } else if data[*index].is_ascii_whitespace() || data[*index] == b',' || data[*index] == b'}' {
415        Ok(())
416    } else {
417        Err(JsonParseFailure::InvalidNumericField)
418    }
419}
420
421fn skip_json_boolean(index: &mut usize, data: &[u8], value: bool) -> Result<(),JsonParseFailure> {
422    let start = *index;
423    let target = if value { "true" } else { "false" };
424    while (*index - start) < target.len() {
425        if *index >= data.len() {
426            return Err(JsonParseFailure::Incomplete)
427        }
428        if data[*index] != target.as_bytes()[*index-start] {
429            return Err(JsonParseFailure::InvalidBooleanField);
430        }
431        *index += 1;
432    }
433    Ok(())
434}
435
436fn skip_whitespace(index: &mut usize, data: &[u8]) -> Result<(),JsonParseFailure> {
437    while *index < data.len() && data[*index].is_ascii_whitespace() {
438        *index += 1;
439    }
440    if *index == data.len() {
441        Err(JsonParseFailure::Incomplete)
442    } else {
443        Ok(())
444    }
445}
446
447/// the core function that powers serialization in the JsonObject API. It attempts to serialize the provided fields as a JSON object into the provided output, & returns the number of bytes written on success.
448pub fn serialize_json_object<
449'data,
450Output: Write,
451>(
452    mut output: Output,
453    fields: &[JsonField<'data,'data>],
454) -> Result<usize, Output::Error> {
455    let mut ret = 0;
456    tracked_write(&mut output,&mut ret , "{")?;
457    let mut field_needs_comma = false;
458    for field in fields.as_ref().iter() {
459        if field_needs_comma {
460            tracked_write(&mut output,&mut ret , ",")?;
461        } else {
462            field_needs_comma = true;
463        }
464        write_escaped_json_string(&mut output, &mut ret , field.key)?;
465        tracked_write(&mut output, &mut ret , ":")?;
466        match field.value {
467            JsonValue::String(s) => {
468                write_escaped_json_string(&mut output, &mut ret , s)?;
469            },
470            JsonValue::Boolean(false) => {
471                tracked_write(&mut output,&mut ret , "false")?;
472            },
473            JsonValue::Boolean(true) => {
474                tracked_write(&mut output,&mut ret , "true")?;
475            },
476            JsonValue::Number(n) => {
477                tracked_write(&mut output,&mut ret , &base10::i64(n))?;
478            },
479        }
480    }
481    tracked_write(&mut output, &mut ret , "}")?;
482    Ok(ret)
483}
484
485
486fn tracked_write<T: Write>(mut output: T, counter: &mut usize, data: &str) -> Result<(), T::Error> {
487    output.write_all(data.as_bytes())?;
488    *counter += data.len();
489    Ok(())
490}
491
492fn write_escaped_json_string<T: Write>(mut output: T, counter: &mut usize, data: &str) -> Result<(), T::Error> {
493    tracked_write(&mut output, &mut *counter, "\"")?;
494    for field_character in data.chars() {
495        if field_character == '"' {
496            tracked_write(&mut output, &mut *counter, unsafe { core::str::from_utf8_unchecked(&[b'\\', field_character as u8]) })?;
497        } else {
498            tracked_write(&mut output, &mut *counter, unsafe { core::str::from_utf8_unchecked(&[field_character as u8]) })?;
499        }
500    }
501    tracked_write(&mut output, &mut *counter, "\"")?;
502    Ok(())
503}
504
505
506#[cfg(feature = "alloc")]
507mod alloc {
508
509    extern crate alloc as alloclib;
510    use core::convert::Infallible;
511
512    use alloclib::string::String;
513    use embedded_io::ErrorType;
514
515    use crate::StringWrite;
516
517    struct _StringWrapper<T: ?Sized> {
518        inner: T
519    }
520
521    impl<T: AsMut<String>> ErrorType for _StringWrapper<T> {
522        type Error = Infallible;
523    }
524
525    impl<T: AsMut<String>> StringWrite for _StringWrapper<T> {
526        fn write_string(&mut self, data: &str) -> (usize,Result<(), <Self as ErrorType>::Error>) {
527            self.inner.as_mut().push_str(data);
528            (data.len(), Ok(()))
529        }
530    }
531}
532
533#[cfg(feature = "std")]
534mod std {
535    extern crate std as stdlib;
536    use embedded_io_adapters::std::FromStd as StdIoAdapter;
537    use stdlib::io::Error as StandardLibIoError;
538    use stdlib::io::Write as StandardLibIoWrite;
539
540    use crate::FieldBuffer;
541    use crate::JsonObject;
542
543    impl <'a,T: FieldBuffer<'a>> JsonObject<T> {
544        /// convenience method to serialize after wrapping std::io::Write with embedded_io_adapters::std::FromStd
545        pub fn serialize_std<Output: StandardLibIoWrite>(&self, output: Output) -> Result<usize,StandardLibIoError> {
546            self.serialize_into(StdIoAdapter::new(output))
547        }
548    }
549}
550
551#[cfg(test)]
552mod tests {
553
554    use super::*;
555
556    #[test]
557    fn test_serialize_object_empty() {
558        let mut buffer = [0_u8; 1000];
559        let test_map = ArrayJsonObject::<50>::new();
560        let n = test_map.serialize_into(buffer.as_mut_slice()).unwrap();
561        assert_eq!(b"{}", buffer.split_at(n).0)
562    }
563
564    #[test]
565    fn test_serialize_object_simple() {
566        let mut buffer = [0_u8; 1000];
567        let mut test_map = ArrayJsonObject::<50>::new();
568        test_map.push_field("sub", JsonValue::String("1234567890")).unwrap();
569        test_map.push_field("name", JsonValue::String("John Doe")).unwrap();
570        test_map.push_field("iat", JsonValue::Number(1516239022)).unwrap();
571        test_map.push_field("something", JsonValue::Boolean(false)).unwrap();
572        let n = test_map.serialize_into(buffer.as_mut_slice()).unwrap();
573        assert_eq!(br#"{"sub":"1234567890","name":"John Doe","iat":1516239022,"something":false}"#, buffer.split_at(n).0)
574    }
575
576    #[test]
577    fn test_parse_object_success_empty() {
578        let (bytes_consumed,json_object) = ArrayJsonObject::<0>::new_parsed(b"{}").unwrap();
579        assert!(json_object.fields().is_empty());
580        assert_eq!(bytes_consumed, 2);
581    }
582
583    #[test]
584    fn test_parse_object_success_simple() {
585        let data = br#"{"sub":"1234567890","name":"John Doe","iat":1516239022,"something":false}"#;
586        let (data_end,json_object) = ArrayJsonObject::<50>::new_parsed(data).unwrap();
587        assert_eq!(data_end, data.len());
588        let test_fields = json_object.fields();
589        assert_eq!(4, test_fields.len());
590        assert_eq!(JsonField { key: "sub", value: JsonValue::String("1234567890")}, test_fields[0]);
591        assert_eq!(JsonField { key: "name", value: JsonValue::String("John Doe")}, test_fields[1]);
592        assert_eq!(JsonField { key: "iat", value: JsonValue::Number(1516239022)}, test_fields[2]);
593        assert_eq!(JsonField { key: "something", value: JsonValue::Boolean(false)}, test_fields[3]);
594    }
595
596    #[test]
597    fn test_parse_object_failure_incomplete_simple() {
598        match ArrayJsonObject::<50>::new_parsed(b"{") {
599            Err(JsonParseFailure::Incomplete) => {},
600            _ => panic!("incomplete json")
601        }
602    }
603
604    #[test]
605    fn test_parse_object_failure_incomplete_brace() {
606        match ArrayJsonObject::<50>::new_parsed(br#"{"sub":"1234567890","name":"John Doe","iat":1516239022,"something":false"#) {
607            Err(JsonParseFailure::Incomplete) => {},
608            other => panic!("{:?}", other)
609        }
610    }
611
612    #[test]
613    fn test_parse_object_failure_too_many_fields() {
614        match ArrayJsonObject::<0>::new_parsed(br#"{"some":"thing"}"#) {
615            Err(JsonParseFailure::TooManyFields) => {},
616            other => panic!("{:?}", other)
617        }
618    }
619
620}