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