added a readme
This commit is contained in:
+8
-2
@@ -3,8 +3,14 @@ name = "json_dotpath"
|
||||
version = "0.1.0"
|
||||
authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
license = "MIT"
|
||||
description = "Dotted path access to nested JSON objects (serde_json::Value)"
|
||||
repository = "https://git.ondrovo.com/packages/json_dotpath"
|
||||
readme = "README.md"
|
||||
keywords = ["serde", "json", "dot"]
|
||||
categories = [
|
||||
"data-structures"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
serde = "1"
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# json_dotpath
|
||||
|
||||
Access members of nested JSON arrays and objects using "dotted paths".
|
||||
|
||||
The `DotPaths` trait is implemented for `serde_json::Value`,
|
||||
`serde_json::Map<String, serde_json::Value>`, and `Vec<serde_json::Value>`.
|
||||
|
||||
Any serializable type or `serde_json::Value` can be stored to or retrieved from
|
||||
the nested object. Any value stored in the object can also be modified in place
|
||||
by getting a mutable reference.
|
||||
|
||||
This crate is useful for tasks such as working with dynamic JSON API payloads,
|
||||
parsing config files, or polymorphic data store.
|
||||
|
||||
## Supported Operations
|
||||
|
||||
### Object and Array
|
||||
- Set (dropping the original value, if any)
|
||||
- Remove (remove and drop a value)
|
||||
- Take (remove a value and deserialize it)
|
||||
- Replace (take and set)
|
||||
- Get (find & deserialize)
|
||||
- Get a mutable reference to a Value
|
||||
|
||||
### Array
|
||||
Array is an ordered sequence backed by a Vec. It has these additional operations:
|
||||
|
||||
- Prepend
|
||||
- Append
|
||||
- Insert, shifting the following elements
|
||||
- Get the last element
|
||||
|
||||
### Null
|
||||
JSON null can become an array or object by setting it's members (even nested), as if it was an array or object.
|
||||
It becomes an array or object of the appropriate type based on the root key.
|
||||
|
||||
## Dotted Path Syntax
|
||||
|
||||
Array keys must be numeric (integer), or one of the special patterns listed below.
|
||||
|
||||
To avoid ambiguity, it's not allowed to use numeric keys (or keys starting with a number)
|
||||
as map keys. Map keys must start with an ASCII letter or underscore and must not contain a dot (`.`).
|
||||
|
||||
### Array Index Patterns
|
||||
|
||||
- `-` ... prepend
|
||||
- `<` ... prepend (or get first)
|
||||
- `+` ... append
|
||||
- `>` ... append (or get last)
|
||||
- `<n`, e.g. `<5` ... insert before the n-th element
|
||||
- `>n`, e.g. `>5` ... insert after the n-th element
|
||||
|
||||
### Path Examples
|
||||
|
||||
- Empty path ... access the root element
|
||||
- `5` ... get the element `"five"` from `[0,1,2,3,4,"five"]`
|
||||
- `a.b.c` ... get `1` from `{ "a": { "b": { "c": 1 } } }`
|
||||
- `a.0.x` ... get `1` from `{ "a": [ { "x": 1 } ] }`
|
||||
|
||||
It's possible to create nested arrays or objects by setting a non-existent path,
|
||||
provided the key syntax rules are maintained.
|
||||
|
||||
See unit tests for more examples.
|
||||
+48
@@ -4,6 +4,8 @@ use serde_json::{Map, Value};
|
||||
use std::cmp::Ordering;
|
||||
use std::mem;
|
||||
|
||||
#[macro_use] extern crate serde_derive;
|
||||
|
||||
/// Access and mutate nested JSON elements by dotted paths
|
||||
///
|
||||
/// The path is composed of keys separated by dots, e.g. `foo.bar.1`.
|
||||
@@ -540,6 +542,7 @@ mod tests {
|
||||
use crate::DotPaths;
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use serde::{Serialize,Deserialize};
|
||||
|
||||
#[test]
|
||||
fn get_scalar_with_empty_path() {
|
||||
@@ -804,4 +807,49 @@ mod tests {
|
||||
);
|
||||
assert_eq!(json!({"one": "two", "x": {"bbb": ["betelgeuze"]}}), vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stamps() {
|
||||
let mut stamps = Value::Null;
|
||||
// null will become Value::Array(vec![])
|
||||
|
||||
#[derive(Serialize,Deserialize,PartialEq,Default)]
|
||||
struct Stamp {
|
||||
country: String,
|
||||
year: u32,
|
||||
color: String,
|
||||
#[serde(rename = "face value")]
|
||||
face_value: String,
|
||||
};
|
||||
|
||||
stamps.dot_set("0", json!({
|
||||
"country": "British Mauritius",
|
||||
"year": 1847,
|
||||
"color": "orange",
|
||||
"face value": "1 penny"
|
||||
}));
|
||||
|
||||
// append
|
||||
stamps.dot_set(">", Stamp {
|
||||
country: "British Mauritius".to_string(),
|
||||
year: 1847,
|
||||
color: "blue".to_string(),
|
||||
face_value: "2 pence".to_string(),
|
||||
});
|
||||
|
||||
assert_eq!("orange", stamps.dot_get::<String>("0.color").unwrap());
|
||||
assert_eq!("blue", stamps.dot_get::<String>("1.color").unwrap());
|
||||
|
||||
assert_eq!(1847, stamps.dot_get::<Stamp>("1").unwrap().year);
|
||||
|
||||
// Remove the first stamp's "face value" attribute
|
||||
assert_eq!(Some("1 penny".to_string()), stamps.dot_get("0.face value"));
|
||||
stamps.dot_remove("0.face value");
|
||||
assert_eq!(Option::<Value>::None, stamps.dot_get("0.face value"));
|
||||
|
||||
// change the second stamp's year
|
||||
let old_year : u32 = stamps.dot_replace("1.year", 1850).unwrap();
|
||||
assert_eq!(1847, old_year);
|
||||
assert_eq!(1850, stamps.dot_get::<u32>("1.year").unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user