#[macro_use] extern crate jzon; use jzon::codegen::Generator; use jzon::object::Object; use jzon::JsonValue; use std::io; /// Custom generator that sort keys by name; based on DumpGenerator. pub struct CustomGenerator { code: Vec, } impl CustomGenerator { pub fn new() -> Self { CustomGenerator { code: Vec::with_capacity(1024), } } pub fn consume(self) -> String { // Original strings were unicode, numbers are all ASCII, // therefore this is safe. unsafe { String::from_utf8_unchecked(self.code) } } } impl Generator for CustomGenerator { type T = Vec; #[inline(always)] fn get_writer(&mut self) -> &mut Vec { &mut self.code } #[inline(always)] fn write_min(&mut self, _: &[u8], min: u8) -> io::Result<()> { self.code.push(min); Ok(()) } #[inline(always)] fn write_object(&mut self, object: &Object) -> io::Result<()> { self.write_char(b'{')?; let mut entries: Vec<(&str, &JsonValue)> = Vec::new(); for (k, v) in object.iter() { entries.push((k, v)); } entries.sort_by(|(k1, _), (k2, _)| k1.partial_cmp(k2).unwrap()); let mut iter = entries.iter(); if let Some((key, value)) = iter.next() { self.indent(); self.new_line()?; self.write_string(key)?; self.write_min(b": ", b':')?; self.write_json(value)?; } else { self.write_char(b'}')?; return Ok(()); } for (key, value) in iter { self.write_char(b',')?; self.new_line()?; self.write_string(key)?; self.write_min(b": ", b':')?; self.write_json(value)?; } self.dedent(); self.new_line()?; self.write_char(b'}') } } #[test] fn object_keys_sorted() { let o = object! { c: null, b: null, a: null, }; let mut gen = CustomGenerator::new(); gen.write_json(&o).expect("Can't fail"); let json = gen.consume(); let dump = o.dump(); assert_eq!(json, r#"{"a":null,"b":null,"c":null}"#); assert_eq!(dump, r#"{"c":null,"b":null,"a":null}"#); assert_ne!(json, dump); }