1extern crate serde_json;
2extern crate regex;
3
4mod tokenizer;
5mod requests;
6
7use serde_json::Value;
8
9use tokenizer::*;
10use requests::*;
11
12pub fn lookup(json: String, json_path: String) -> Result<String, String> {
13 serde_json::from_str(json.as_str())
14 .map_err(|_| s("Unable to parse json"))
15 .and_then(|v| look(&v, &v, json_path))
16}
17
18pub fn look(root: &Value, json: &Value, json_path: String) -> Result<String,String> {
19 let tokens = tokenize(json_path);
20 tokens.and_then(|token_list| {
21 token_list.iter().fold(Ok(json.clone()), |value, token| {
22 value.and_then(|v| {
23 let operation = parse_token(token.clone());
24 operation.and_then(|op| request_json(&root, &v, &op))
25 })
26 })
27 })
28 .and_then(|res| {
29 serde_json::to_string(&res).map_err(|_| s("Unable to convert result"))
30 })
31}
32
33pub fn find_filter(root: &Value, json: &Value, args: &Vec<String>) -> Result<Value,String> {
34 let res_values = args.iter().map(|arg| {
35 let filter = parse_filter(arg.to_string());
36 let res: Result<Vec<Value>, String> = filter.and_then(|parsed_filter| {
37 let values: Result<Vec<Value>, String> = json.as_array()
38 .map(|array| {
39 array.iter().filter(|value| {
40 println!("{:?}", serde_json::to_string(value).unwrap());
41 let left = eval_expression(root, value, parsed_filter.left.clone());
42 let right = eval_expression(root, value, parsed_filter.right.clone());
43 if let (Ok(l),Ok(r)) = (left,right) {
44 eval_filter(l.as_str(), parsed_filter.op.as_str(), r.as_str())
45 } else {
46 false
47 }
48 })
49 .map(|value| value.clone())
50 .collect::<Vec<Value>>()
51 })
52 .ok_or(s("Unable to filter json"));
53 values
54 });
55 println!("res: {:?}", res);
56 res
57 })
58 .collect::<Result<Vec<Vec<Value>>, String>>();
59 res_values.map(|arg| {
60 arg.into_iter().flat_map(|arg| { arg.into_iter() }).collect::<Vec<Value>>()
61 }).map(|value| Value::Array(value))
62}
63
64pub fn eval_expression(root: &Value, json: &Value, expression: String) -> Result<String,String> {
65 if !expression.contains("$") && !expression.contains("@") {
66 Ok(expression)
67 } else {
68 look(root, json, expression)
69 }
70}
71
72pub fn request_json(root: &Value, json: &Value, operation: &ParsedJsonPath) -> Result<Value,String> {
73 match operation.op.as_str() {
74 "root" => Ok(root.clone()),
75 "child" => Ok(json.clone()),
76 "key" => Ok(find_key(json, operation.key.as_str())),
77 "scan" => {
78 let res = search_key(json, operation.key.as_str(), &vec![]);
79 println!("filter: {:?}", res);
80 Ok(Value::Array(res))
81 }
82 "idx" => find_indexes(json, &operation.args),
83 "range" => find_range(json, &operation.args),
84 "filter" => {
85 let res = find_filter(root, json, &operation.args);
86 println!("filter: {:?}", res);
87 res
88 }
89 _ => Err(s("Unable to parse JsonPath expression")),
90 }
91}
92
93#[cfg(test)]
94mod tests {
95
96 use tokenizer::s;
97 use super::*;
98
99 #[test]
100 fn it_lookup() {
101 let data = r#"
102 {
103 "firstName": "John",
104 "lastName" : "doe",
105 "age" : 26,
106 "address" : {
107 "streetAddress": "naist street",
108 "city" : "Nara",
109 "type" : "630-0192"
110 },
111 "phoneNumbers": [
112 {
113 "type" : {"name": "iPhone", "type":"test"},
114 "number": "0123-4567-8888"
115 },
116 {
117 "type" : "home",
118 "number": "0123-4567-8910"
119 }
120 ]
121 }
122 "#;
123 let jsonpath = "$..type[*].name";
124 let res = lookup(s(data), s(jsonpath)).unwrap();
125 let expected = r#"["iPhone"]"#;
126 assert_eq!(res, expected);
127 }
128
129 #[test]
130 fn it_lookup_with_filter() {
131 let data = r#"
132 {
133 "firstName": "John",
134 "lastName" : "doe",
135 "age" : 26,
136 "address" : {
137 "streetAddress": "naist street",
138 "city" : "Nara",
139 "type" : "630-0192"
140 },
141 "phoneNumbers": [
142 {
143 "type" : {"name": "iPhone", "type":"test"},
144 "number": "0123-4567-8888"
145 },
146 {
147 "type" : "home",
148 "number": "0123-4567-8910"
149 }
150 ]
151 }
152 "#;
153 let jsonpath = r#"$.phoneNumbers[?(@.number == "0123-4567-8910")].type"#;
154 let res = lookup(s(data), s(jsonpath)).unwrap();
155 let expected = r#"["home"]"#;
156 assert_eq!(res, expected);
157 }
158}