Skip to content

Commit

Permalink
feat: support optional json path as first argument on RadonOpCodes::S…
Browse files Browse the repository at this point in the history
…tringParseJSONMap
  • Loading branch information
guidiaz committed Jan 10, 2024
1 parent f492676 commit f222ee5
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 10 deletions.
74 changes: 73 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rad/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ if_rust_version = "1.0.0"
# the http crate is used to perform additional validations before passing arguments to the surf http client
# the version of http must be kept in sync with the version used by surf
http = "0.2.1"
jsonpath = "0.1.1"
log = "0.4.8"
minidom = { git = "https://github.com/witnet/xmpp-rs", rev = "bc8a33ff5da95ee4039ad7ee3376c100d9e35c74" }
num_enum = "0.4.2"
Expand Down
9 changes: 9 additions & 0 deletions rad/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ pub enum RadError {
description
)]
JsonParse { description: String },
/// The given JSON path is not present in a JSON-stringified object
#[fail(display = "Failed to find JSON path `{}` from RadonString", path)]
JsonPathNotFound { path: String },
/// Failed to parse a JSON path selector from a string value
#[fail(
display = "Failed to parse a JSON path from a string value: {:?}",
description
)]
JsonPathParse { description: String },
/// Failed to parse an object from a XML buffer
#[fail(
display = "Failed to parse an object from a XML buffer: {:?}",
Expand Down
42 changes: 34 additions & 8 deletions rad/src/operators/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ use std::{
use base64::Engine;
use serde_cbor::value::{from_value, Value};
use serde_json::Value as JsonValue;
use jsonpath::Selector;

use slicestring::Slice;
use regex::Regex;
use witnet_data_structures::radon_error::RadonError;

use crate::{
error::RadError,
Expand Down Expand Up @@ -142,18 +144,42 @@ pub fn parse_json(input: &RadonString) -> Result<RadonTypes, RadError> {
serde_json::from_str(&input.value()).map_err(|err| RadError::JsonParse {
description: err.to_string(),
})?;

RadonTypes::try_from(json_value)
}

pub fn parse_json_map(input: &RadonString) -> Result<RadonMap, RadError> {
let item = parse_json(input)?;
item.try_into()
}
pub fn parse_json_map(input: &RadonString, args: &Option<Vec<Value>>) -> Result<RadonMap, RadError> {
let not_found = |json_path: &str| RadError::JsonPathNotFound {
path: String::from(json_path)
};

let wrong_args = || RadError::WrongArguments {
input_type: RadonString::radon_type_name(),
operator: "ParseJsonMap".to_string(),
args: args.to_owned().unwrap_or_default(),
};

let json_input: JsonValue = serde_json::from_str(&input.value())
.map_err(|err| RadError::JsonParse {
description: err.to_string(),
})?;

match args.to_owned().unwrap_or_default().get(0) {
Some(Value::Text(json_path)) => {
let selector = Selector::new(json_path.as_str())
.map_err(|err| RadError::JsonPathParse {
description: err.to_string(),
})?;
let item = selector.find(&json_input)
.next()
.ok_or_else(|| not_found(json_path.as_str()))?;
RadonTypes::try_from(item.to_owned())?.try_into()
},
None => {
RadonTypes::try_from(json_input)?.try_into()
},
_ => Err(wrong_args())
}

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

fn add_children(
Expand Down
2 changes: 1 addition & 1 deletion rad/src/types/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ impl Operable for RadonString {
(RadonOpCodes::StringParseJSONArray, None) => string_operators::parse_json_array(self)
.map(RadonTypes::from)
.map_err(Into::into),
(RadonOpCodes::StringParseJSONMap, None) => string_operators::parse_json_map(self)
(RadonOpCodes::StringParseJSONMap, args) => string_operators::parse_json_map(self, &args)
.map(RadonTypes::from)
.map_err(Into::into),
(RadonOpCodes::StringParseXMLMap, None) => string_operators::parse_xml_map(self)
Expand Down

0 comments on commit f222ee5

Please sign in to comment.