# hson
JSON like format for HTML.
The parser can be used for other purposes, but its main goal is to represent a HTML structure in a JSON style.
Allow to query the data the same way the DOM is queried client-side through `QuerySelectorAll` method.
## Main differences with standard json
* Allow same key multiple times in same object
## Usage
[Parsing](#Parsing)
[Stringifying](#Stringifying)
[Searching](#Searching)
[Inserting](#Inserting)
[Removing](#Removing)
[Iterating](#Iterating)
[Debugging](#Debugging)
[Events listening](#Events)
[Nodes manipulation](#Manipulation)
### Parsing
```rust
use hson::{ Hson, Debug };
...
let data = r#"{
"div": {
"attrs": {
"class": [""],
"onClick": "doSomething"
},
"div": {
"p": {
"attrs": {},
"span": {
"text": "Hello"
}
},
"p": {}
},
"div": {
"component": "test",
"attrs": {},
"onClick": "componentDoSomething"
}
}
}"#;
let mut hson = Hson::new();
hson.parse(&data).unwrap();
hson.print_data(true);
```
### Stringifying
```rust
...
let s = hson.stringify();
println!("{}", &s);
```
### Searching
Search is similar to the javascript `querySelectorAll` method.
```rust
use hson::{ Hson, Query, Search };
...
// Standard recursive search
let results = hson.search("div p").unwrap();
println!("\n{:?}\n", results);
// Look for immediate childs, no recursive search
let results = hson.search("div>p").unwrap();
println!("\n{:?}\n", results);
// Look for multiple childs (OR search)
let results = hson.search("attrs id|rate|trusted").unwrap();
println!("\n{:?}\n", results);
// Look for a node with a specific value
let results = hson.search("attrs id='12'").unwrap();
println!("\n{:?}\n", results);
// All those features can be combined
let results = hson.search("div>p attrs id='12'|rate='3'|trusted").unwrap();
println!("\n{:?}\n", results);
// Look for childs in a specific node, no recursion
let results = hson.search_in(node_id, "div>p").unwrap();
println!("\n{:?}\n", results);
let results = hson.search_in(node_id, ">p").unwrap();
println!("\n{:?}\n", results);
```
### Inserting
```rust
use hson::{ Hson, Query, Ops, Debug };
...
let results = hson.query("div p").unwrap();
let child = r#"{
"i": {
"class": [],
"text": "World"
},
"ul": {
"class": ["active","test"]
}
}"#;
hson.insert(results[0], 1, child).unwrap();
hson.print_data(true);
```
### Removing
```rust
use hson::{ Hson, Query, Ops, Debug };
...
let results = hson.query("p").unwrap();
hson.remove(results[0]).unwrap();
hson.print_data(true);
```
### Iterating
Iterate over the nodes identifiers
```rust
...
for id in hson {
println!("{}", id);
}
// OR
loop {
let id = match hson.next() {
Some(s) => s,
None => break
};
match &hson.nodes.get(&id) {
Some(node) => {
println ! ("{} : {}", node.instance, node.id);
}
None => {
break
}
}
}
```
### Debugging
```rust
use hson::{ Hson, Debug };
...
hson.print_process_time();
hson.print_nodes(true); // true for sorted printing
hson.print_data(true); // true for pretty printing
```
### Events
Current supported events are _Parse_, _Insert_, _Remove_.
```rust
use hson::{ Hson, Ops, Event };
...
fn on_event (evt: Event, uid: u64) {
println!("\nEVENT : {:?} on {}\n", evt, uid);
}
let mut hson = Hson::new();
hson.subscribe(on_event);
...
```
### Manipulation
Nodes values can be casted to primitive types using `Vertex`, a `Node` clone with more attributes.
_**Note : Vertex are Nodes clones and not references to the underlying Nodes. Manipulating Vertex's values will not be reflected on their matching Nodes.**_
```rust
use hson::{ Hson, Query, Search, Cast };
...
let results = hson.search("div attrs class").unwrap();
let vertex = hson.get_vertex(results[0]).unwrap();
// Get vertex value as u64
println!("{}", vertex.value_as_f64());
// Get vertex value as a vector of String
println!("{:?}", vertex.value_as_array());
// Cast a string value to a different type
let s = "0.456";
println!("{}", vertex.as_f64(s));
```
##### Vertex methods
* `fn key_as_string (&self) -> Option`
* `fn key_as_f64 (&self) -> Option`
* `fn key_as_i64 (&self) -> Option`
* `fn key_as_u64 (&self) -> Option`
* `fn key_as_bool (&self) -> Option`
* `fn value_as_string (&self) -> Option`
* `fn value_as_f64 (&self) -> Option`
* `fn value_as_i64 (&self) -> Option`
* `fn value_as_u64 (&self) -> Option`
* `fn value_as_bool (&self) -> Option`
* `fn value_as_array (&self) -> Option>`
* `fn as_f64 (&self, value: &str) -> Option`
* `fn as_i64 (&self, value: &str) -> Option`
* `fn as_u64 (&self, value: &str) -> Option`
* `fn as_bool (&self, value: &str) -> Option`