ajson/lib.rs
1/*!
2# A-JSON
3Ajson is a lightweight json parser that allows users to dynamically retrieve values in json using a simple syntax.
4
5## Examples
6```
7use ajson::Result;
8fn main() -> Result<()> {
9 let data = r#"
10 {
11 "project": {
12 "name": "ajson",
13 "maintainer": "importcjj",
14 "version": 0.1,
15 "rusts": ["stable", "nightly"]
16 }
17 }
18 "#;
19
20 let name = ajson::get(data, "project.name")?.unwrap();
21 assert_eq!(name, "ajson");
22 Ok(())
23}
24```
25## Syntax
26JSON example
27```text
28{
29 "name": {"first": "Tom", "last": "Anderson"},
30 "age":37,
31 "children": ["Sara","Alex","Jack"],
32 "fav.movie": "Deer Hunter",
33 "friends": [
34 {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
35 {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
36 {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
37 ]
38}
39```
40
41#### basic
42Below is a quick overview of the path syntax, for more complete information please check out GJSON Syntax.
43
44A path is a series of keys separated by a dot. A key may contain special wildcard characters '*' and '?'. To access an array value use the index as the key. To get the number of elements in an array or to access a child path, use the '#' character. The dot and wildcard characters can be escaped with ''.
45
46```text
47name.last >> "Anderson"
48age >> 37
49children >> ["Sara","Alex","Jack"]
50children.# >> 3
51children.1 >> "Alex"
52child*.2 >> "Jack"
53c?ildren.0 >> "Sara"
54fav\.movie >> "Deer Hunter"
55friends.#.first >> ["Dale","Roger","Jane"]
56friends.1.last >> "Craig"
57```
58
59#### Escape character
60Special purpose characters, such as ., *, and ? can be escaped with .
61
62```text
63fav\.movie "Deer Hunter"
64```
65
66#### Arrays
67The # character allows for digging into JSON Arrays.To get the length of an array you'll just use the # all by itself.
68```text
69friends.# 3
70friends.#.age [44,68,47]
71```
72
73#### queries
74You can also query an array for the first match by using #(...), or find all matches with #(...)#. Queries support the ==, !=, <, <=, >, >= comparison operators and the simple pattern matching % (like) and !% (not like) operators.
75
76```text
77friends.#(last=="Murphy").first >> "Dale"
78friends.#(last=="Murphy")#.first >> ["Dale","Jane"]
79friends.#(age>45)#.last >> ["Craig","Murphy"]
80friends.#(first%"D*").last >> "Murphy"
81friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
82```
83
84#### construct
85Basically, you can use selectors to assemble whatever you want, and of course, the result is still a json ;)
86```text
87{name.first,age,"murphys":friends.#(last="Murphy")#.first}
88[name.first,age,children.0]
89```
90*/
91
92#[cfg(feature = "wild")]
93extern crate regex;
94#[cfg(feature = "wild")]
95mod wild;
96
97mod element;
98mod number;
99mod parser;
100mod path;
101mod unescape;
102mod util;
103mod value;
104
105use std::result;
106
107#[doc(hidden)]
108pub use element::compound;
109#[doc(hidden)]
110pub use element::compound_u8;
111pub use number::Number;
112pub use path::Path;
113pub use unescape::unescape;
114pub use value::Value;
115
116#[derive(Debug, PartialEq, Eq)]
117pub enum Error {
118 Path,
119 Eof,
120 ObjectKey,
121 Object,
122 Array,
123}
124
125pub type Result<T> = result::Result<T, Error>;
126
127/// `get` value from JSON string with the specified path, it is relatively loose and
128/// can tolerate some illegal JSON.
129/// ```
130/// use ajson::Result;
131/// fn main() -> Result<()> {
132/// let data = r#"{"name": "ajson"}"#;
133/// let v = ajson::get(data, "name")?.unwrap();
134/// assert_eq!(v, "ajson");
135/// Ok(())
136/// }
137/// ```
138/// If the given JSON is not a valid JSON, then ajson
139/// will try to get the value from the first JSON array
140/// or map it finds.
141/// ```
142/// use ajson::Result;
143/// fn main() -> Result<()> {
144/// let data = r#"someinvalidstring{"name": "ajson"}"#;
145/// let v = ajson::get(data, "name")?.unwrap();
146/// assert_eq!(v, "ajson");
147/// Ok(())
148/// }
149/// ```
150/// If there is no valid JSON array or map in the given JSON,
151/// `get` returns None.
152/// ```should_panic
153/// let data = r#"someinvalidstring"#;
154/// let v = ajson::get(data, "name").unwrap().unwrap();
155/// ```
156pub fn get<'a>(json: &'a str, path: &'a str) -> Result<Option<Value<'a>>> {
157 let path = path::Path::from_slice(path.as_bytes())?;
158 let (a, _left) = parser::bytes_get(json.as_bytes(), &path)?;
159 Ok(a.map(|el| el.to_value()))
160}
161
162/// Returns the first JSON value parsed, and it may be having
163/// problems because it does not actively panic on incomplete
164/// JSON values. For example, array or map are not closed properly.
165/// ```
166/// use ajson::Result;
167/// fn main() -> Result<()> {
168/// let v = ajson::parse(r#"{"name": "ajson"}"#)?.unwrap();
169/// assert!(v.is_object());
170/// let v = ajson::parse(r#"{"name": "ajson""#)?.unwrap();
171/// assert!(v.is_object());
172/// let v = ajson::parse(r#"null,"string", 2"#)?.unwrap();
173/// assert!(v.is_null());
174/// Ok(())
175/// }
176/// ```
177pub fn parse(json: &str) -> Result<Option<Value>> {
178 let (parsed, _left) = element::read_one(json.as_bytes())?;
179
180 Ok(parsed.map(|el| el.to_value()))
181}