Skip to content

Commit f222ee5

Browse files
committed
feat: support optional json path as first argument on RadonOpCodes::StringParseJSONMap
1 parent f492676 commit f222ee5

File tree

5 files changed

+118
-10
lines changed

5 files changed

+118
-10
lines changed

Cargo.lock

+73-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rad/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ if_rust_version = "1.0.0"
1919
# the http crate is used to perform additional validations before passing arguments to the surf http client
2020
# the version of http must be kept in sync with the version used by surf
2121
http = "0.2.1"
22+
jsonpath = "0.1.1"
2223
log = "0.4.8"
2324
minidom = { git = "https://github.com/witnet/xmpp-rs", rev = "bc8a33ff5da95ee4039ad7ee3376c100d9e35c74" }
2425
num_enum = "0.4.2"

rad/src/error.rs

+9
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ pub enum RadError {
3838
description
3939
)]
4040
JsonParse { description: String },
41+
/// The given JSON path is not present in a JSON-stringified object
42+
#[fail(display = "Failed to find JSON path `{}` from RadonString", path)]
43+
JsonPathNotFound { path: String },
44+
/// Failed to parse a JSON path selector from a string value
45+
#[fail(
46+
display = "Failed to parse a JSON path from a string value: {:?}",
47+
description
48+
)]
49+
JsonPathParse { description: String },
4150
/// Failed to parse an object from a XML buffer
4251
#[fail(
4352
display = "Failed to parse an object from a XML buffer: {:?}",

rad/src/operators/string.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ use std::{
77
use base64::Engine;
88
use serde_cbor::value::{from_value, Value};
99
use serde_json::Value as JsonValue;
10+
use jsonpath::Selector;
1011

1112
use slicestring::Slice;
1213
use regex::Regex;
14+
use witnet_data_structures::radon_error::RadonError;
1315

1416
use crate::{
1517
error::RadError,
@@ -142,18 +144,42 @@ pub fn parse_json(input: &RadonString) -> Result<RadonTypes, RadError> {
142144
serde_json::from_str(&input.value()).map_err(|err| RadError::JsonParse {
143145
description: err.to_string(),
144146
})?;
145-
146147
RadonTypes::try_from(json_value)
147148
}
148149

149-
pub fn parse_json_map(input: &RadonString) -> Result<RadonMap, RadError> {
150-
let item = parse_json(input)?;
151-
item.try_into()
152-
}
150+
pub fn parse_json_map(input: &RadonString, args: &Option<Vec<Value>>) -> Result<RadonMap, RadError> {
151+
let not_found = |json_path: &str| RadError::JsonPathNotFound {
152+
path: String::from(json_path)
153+
};
154+
155+
let wrong_args = || RadError::WrongArguments {
156+
input_type: RadonString::radon_type_name(),
157+
operator: "ParseJsonMap".to_string(),
158+
args: args.to_owned().unwrap_or_default(),
159+
};
160+
161+
let json_input: JsonValue = serde_json::from_str(&input.value())
162+
.map_err(|err| RadError::JsonParse {
163+
description: err.to_string(),
164+
})?;
165+
166+
match args.to_owned().unwrap_or_default().get(0) {
167+
Some(Value::Text(json_path)) => {
168+
let selector = Selector::new(json_path.as_str())
169+
.map_err(|err| RadError::JsonPathParse {
170+
description: err.to_string(),
171+
})?;
172+
let item = selector.find(&json_input)
173+
.next()
174+
.ok_or_else(|| not_found(json_path.as_str()))?;
175+
RadonTypes::try_from(item.to_owned())?.try_into()
176+
},
177+
None => {
178+
RadonTypes::try_from(json_input)?.try_into()
179+
},
180+
_ => Err(wrong_args())
181+
}
153182

154-
pub fn parse_json_array(input: &RadonString) -> Result<RadonArray, RadError> {
155-
let item = parse_json(input)?;
156-
item.try_into()
157183
}
158184

159185
fn add_children(

rad/src/types/string.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl Operable for RadonString {
134134
(RadonOpCodes::StringParseJSONArray, None) => string_operators::parse_json_array(self)
135135
.map(RadonTypes::from)
136136
.map_err(Into::into),
137-
(RadonOpCodes::StringParseJSONMap, None) => string_operators::parse_json_map(self)
137+
(RadonOpCodes::StringParseJSONMap, args) => string_operators::parse_json_map(self, &args)
138138
.map(RadonTypes::from)
139139
.map_err(Into::into),
140140
(RadonOpCodes::StringParseXMLMap, None) => string_operators::parse_xml_map(self)

0 commit comments

Comments
 (0)