# 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.
## Main differences with standard json
* Allow same key multiple times in same object
* Does not allow `null` and `undefined`
## Usage
[Parsing](#Parsing)
[Stringifying](#Stringifying)
[Querying](#Querying)
[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_nodes(true);
```
### Stringifying
```rust
...
let s = hson.stringify();
println!("{}", &s);
```
### Querying
#### Find matching nodes
Querying works as the javascript querySelectorAll method but without the 'CSS' features.
(Queries improvement is planned).
```rust
use hson::{ Hson, Query };
...
// Get node's identifiers for easier processing
let results = hson.query("div p").unwrap();
println!("\n{:?}\n", results);
// Get node's reference
let results = hson.query_nodes("div p").unwrap();
println!("\n{:?}\n", results);
// Recursive search in a node
let results = hson.query_on(&uid, "div p", true).unwrap();
println!("\n{:?}\n", results);
// Non recursive search in a node
let results = hson.query_on(&uid, "attrs", false).unwrap();
println!("\n{:?}\n", results);
// Recursive search in a node and get node's reference
let results = hson.query_on_nodes(&node, "div p", true).unwrap();
println!("\n{:?}\n", results);
// Non recursive search in a node and get node's reference
let results = hson.query_on_nodes(&node, "attrs", false).unwrap();
println!("\n{:?}\n", results);
// Get node key
let key = hson.get_node_key(&node);
// Get node value
let value = hson.get_node_value(&node);
```
### Searching
Search allow easier querying.
```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)
// 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
```
### 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: String) {
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<String>`
* `fn key_as_f64 (&self) -> Option<f64>`
* `fn key_as_i64 (&self) -> Option<i64>`
* `fn key_as_u64 (&self) -> Option<u64>`
* `fn key_as_bool (&self) -> Option<bool>`
* `fn value_as_string (&self) -> Option<String>`
* `fn value_as_f64 (&self) -> Option<f64>`
* `fn value_as_i64 (&self) -> Option<i64>`
* `fn value_as_u64 (&self) -> Option<u64>`
* `fn value_as_bool (&self) -> Option<bool>`
* `fn value_as_array (&self) -> Option<Vec<String>>`
* `fn as_f64 (&self, value: &str) -> Option<f64>`
* `fn as_i64 (&self, value: &str) -> Option<i64>`
* `fn as_u64 (&self, value: &str) -> Option<u64>`
* `fn as_bool (&self, value: &str) -> Option<bool>`