From 1585a60ce8582b80792722d067399f30a325b44e Mon Sep 17 00:00:00 2001 From: Marcello Lamonaca Date: Thu, 19 Dec 2024 11:42:28 +0100 Subject: [PATCH] fix array enumeration of complex items resulting in unformatted JSON values --- Cargo.lock | 44 ++++++++++++++++++++++---------------------- Cargo.toml | 2 +- src/lib.rs | 43 +++++++++++++++++++++++++------------------ 3 files changed, 48 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8340140..58c06c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anstream" @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -111,13 +111,13 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "json2env" -version = "0.3.0" +version = "0.3.1" dependencies = [ "clap", "serde_json", @@ -131,9 +131,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -155,18 +155,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -175,9 +175,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -193,9 +193,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "utf8parse" diff --git a/Cargo.toml b/Cargo.toml index 8718836..0ac455a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json2env" -version = "0.3.0" +version = "0.3.1" edition = "2021" authors = ["Marcello Lamonaca "] description = "JSON to Env Var converter" diff --git a/src/lib.rs b/src/lib.rs index 92ce37c..dc676d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,49 +22,56 @@ impl ParseOptions { #[derive(Debug, Clone)] pub struct JsonParser { options: ParseOptions, - vars: Vec, } impl JsonParser { pub fn new(options: ParseOptions) -> Self { - Self { - options, - vars: vec![], - } + Self { options } } - pub fn parse(&mut self, json: &Value) -> &Vec { - Self::parse_keys(&mut self.vars, "", json, &self.options); - &self.vars + pub fn parse(&mut self, json: &Value) -> Vec { + Self::parse_value("", json, &self.options) } - fn parse_keys(lines: &mut Vec, key: &str, value: &Value, options: &ParseOptions) { + fn parse_value(key: &str, value: &Value, options: &ParseOptions) -> Vec { match value { Value::Array(array) => { - if options.enumerate_array { + let has_complex_values = array + .iter() + .any(|value| value.is_object() || value.is_array()); + + // complex (nested) values cannot be part of an array enumeration, skip just this array + if options.enumerate_array || has_complex_values { + let mut values = Vec::with_capacity(array.len()); + for (index, item) in array.iter().enumerate() { let key = Self::build_key(key, &index.to_string(), &options.key_separator); - Self::parse_keys(lines, &key, item, options) + values.push(Self::parse_value(&key, item, options)); } + + values.into_iter().flatten().collect() } else { let value = array .iter() - .map(ToString::to_string) + .map(|value| value.to_string().replace(['\\', '"'], "")) .collect::>() .join(&options.array_separator); - let item = serde_json::Value::String(value); - - Self::parse_keys(lines, key, &item, options) + let value = serde_json::Value::String(value); + Self::parse_value(key, &value, options) } } Value::Object(object) => { - for (name, value) in object { + let mut values = Vec::with_capacity(object.len()); + + for (name, value) in object.iter() { let key = Self::build_key(key, name, &options.key_separator); - Self::parse_keys(lines, &key, value, options) + values.push(Self::parse_value(&key, value, options)); } + + values.into_iter().flatten().collect() } - _ => lines.push(EnvVar(key.trim().to_owned(), value.clone())), + _ => vec![EnvVar(key.trim().to_owned(), value.clone())], } }