From 1c987b976c3726b31293a8b8fdf7ec628ee7fb2f Mon Sep 17 00:00:00 2001 From: Harry Bachrach Date: Sun, 8 Mar 2020 22:23:31 -0700 Subject: [PATCH] feat: add support for JSON5 Should allow for easier copying and pasting --- Cargo.lock | 199 +++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + README.md | 11 +++ src/json.rs | 45 ++++++++-- src/json_properties.rs | 3 +- src/lib.rs | 6 ++ 6 files changed, 247 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2415a07..9790d3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,39 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + [[package]] name = "clap" version = "2.33.0" @@ -41,6 +74,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + [[package]] name = "either" version = "1.5.3" @@ -53,6 +95,21 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + [[package]] name = "heck" version = "0.3.1" @@ -86,19 +143,94 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +[[package]] +name = "json5" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fb48cdfbe18a1ef5ce0a0edc30b8b8f61422f7073f709dd09311c2b3d2bba6" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn 1.0.16", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +dependencies = [ + "maplit", + "pest", + "sha-1", +] + [[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +dependencies = [ + "unicode-xid 0.2.0", ] [[package]] @@ -107,7 +239,16 @@ version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2", + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +dependencies = [ + "proc-macro2 1.0.9", ] [[package]] @@ -117,6 +258,7 @@ dependencies = [ "atty", "exitcode", "itertools", + "json5", "serde_json", "structopt", ] @@ -144,6 +286,18 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + [[package]] name = "strsim" version = "0.8.0" @@ -167,9 +321,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" dependencies = [ "heck", - "proc-macro2", - "quote", - "syn", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", ] [[package]] @@ -178,9 +332,20 @@ version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +dependencies = [ + "proc-macro2 1.0.9", + "quote 1.0.3", + "unicode-xid 0.2.0", ] [[package]] @@ -192,6 +357,18 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "ucd-trie" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" + [[package]] name = "unicode-segmentation" version = "1.6.0" @@ -210,6 +387,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + [[package]] name = "vec_map" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index d5825c5..15cd8c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ exitcode = "1.1.2" serde_json = "1.0" atty = "0.2" itertools= "0.8.2" +json5 = "0.2.5" diff --git a/README.md b/README.md index 6f33ccf..8b8d1f4 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,11 @@ optional. Only key names are really relevant here. Note that entities other than objects and empty objects are ignored. +Note that all [JSON5][json5] syntax is accepted. JSON5 is a superset of JSON +with support for different types of quotes, comments, etc., so you can much more +easily copy from an actual JavaScript environment. See the [JSON5 +website][json5] for more details. + ### JSON with properties (`-f jsonprop`) ```json @@ -180,6 +185,11 @@ names are ignored: } ``` +Note that all [JSON5][json5] syntax is accepted. JSON5 is a superset of JSON +with support for different types of quotes, comments, etc., so you can much more +easily copy from an actual JavaScript environment. See the [JSON5 +website][json5] for more details. + By default, this format looks for the properties `name` for what to print for each item and `children` for what items are immediate descendants. To change this, you can use the `--template` and `--children` options, respectively. @@ -214,4 +224,5 @@ This project respects [semantic versioning][semver]. [lisp-parser-python]: https://norvig.com/lispy.html [rustup-instructions]: https://rustup.rs/ [ruut-releases]: https://github.com/HarrisonB/ruut/releases +[json5]: https://json5.org/ [semver]: https://semver.org/ diff --git a/src/json.rs b/src/json.rs index 0f80b35..4c08b16 100644 --- a/src/json.rs +++ b/src/json.rs @@ -1,13 +1,12 @@ use super::{Error, Node}; -use serde_json; +use json5; use serde_json::Value as JsonValue; -use std::convert::From; pub fn deserialize(serialized: String) -> Result { if serialized.trim().is_empty() { return Err(Error::EmptyInputError); } - let root_value: JsonValue = serde_json::from_str(&serialized)?; + let root_value: JsonValue = json5::from_str(&serialized)?; match root_value { JsonValue::Object(map) => { if map.len() > 1 { @@ -38,12 +37,6 @@ fn json_value_to_node(name: String, value: &JsonValue) -> Node { } } -impl From for Error { - fn from(serde_error: serde_json::error::Error) -> Error { - Error::FormatSpecificError(format!("{}", serde_error)) - } -} - #[cfg(test)] mod tests { use super::*; @@ -134,4 +127,38 @@ mod tests { } ); } + #[test] + fn good_json5() { + let json = r#" + { + cool: { + // A comment + beans: { + man: null, + }, + wow: null, + } + } + "#; + let root_node = deserialize(json.to_string()).unwrap(); + assert_eq!( + root_node, + Node { + name: "cool".to_string(), + children: vec![ + Node { + name: "beans".to_string(), + children: vec![Node { + name: "man".to_string(), + children: Vec::new() + }] + }, + Node { + name: "wow".to_string(), + children: Vec::new() + } + ] + } + ); + } } diff --git a/src/json_properties.rs b/src/json_properties.rs index d45ab95..2a40bbe 100644 --- a/src/json_properties.rs +++ b/src/json_properties.rs @@ -1,6 +1,7 @@ mod template; use super::{Error, Node}; +use json5; use serde_json; use serde_json::Map; use serde_json::Value as JsonValue; @@ -15,7 +16,7 @@ pub fn deserialize( if serialized.trim().is_empty() { return Err(Error::EmptyInputError); } - let root_value: JsonValue = serde_json::from_str(&serialized)?; + let root_value: JsonValue = json5::from_str(&serialized)?; let template = Template::new(template_str)?; match root_value { JsonValue::Array(vec) => { diff --git a/src/lib.rs b/src/lib.rs index c6d0acf..9a6dfea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,12 @@ pub enum Error { FormatSpecificError(String), } +impl From for Error { + fn from(serde_error: json5::Error) -> Error { + Error::FormatSpecificError(format!("{}", serde_error)) + } +} + pub fn prettify( serialized: String, format: InputFormat,