another_json_minimal 0.0.2

A minimal json crate.
Documentation
# json_minimal

A minimal json crate conforming to https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf .

## Tutorial (creating jsons)

In order to create a valid (i.e. generally accepted) json you should always start with:
```rust
    use json_minimal::*;

    let mut json = Json::new();
    // which is equivalent to
    let mut json = Json::JSON(Vec::new());
    // ...
```

To add an object, simply do this:
```rust
    // ...
    let greeting = 
        Json::OBJECT {
            name: String::from("Greeting"),

            value: Box::new(
                Json::STRING( String::from("Hello, world!") )
            )
        }
    ;

    json.add(greeting);
    // ...
```
or alternatively:
```rust
    // ...
    json.add(
        Json::OBJECT {
            name: String::from("Greeting"),

            value: Box::new(
                Json::STRING( String::from("Hello, world!") )
            )
        }
    );
    // ...
```

As you can see, whilst the crate is minimal (in my opinion) it may not be the quickest to work with. This becomes clearer when adding an array to an object:
```rust
    // ...

    let mut days_in_the_week =
        Json::OBJECT {
            name: String::from("Days of the week"),

            value: Box::new(
                Json::JSON(Vec::new())
            )
        }
    ;

    let mut days = Json::ARRAY(Vec::new());

    days
        .add(
            Json::STRING( String::from("Monday") )
        )
        .add(
            Json::STRING( String::from("Tuesday") )
        )
        .add(
            Json::STRING( String::from("Wednesday") )
        )
        .add(
            Json::STRING( String::from("Thursday") )
        )
        .add(
            Json::STRING( String::from("Friday") )
        )
        .add(
            Json::STRING( String::from("Saturday") )
        )
        .add(
            Json::STRING( String::from("Sunday") )
        )
    ;

    days_in_the_week
        .add(
            Json::OBJECT {
                name: String::from("Total number of days"),

                value: Box::new(
                    Json::NUMBER(7.0) // Accepts `f64`
                )
            }
        )
        .add(
            Json::OBJECT {
                name: String::from("They are called"),

                value: Box::new(
                    days
                )
            }
        )
    ;

    json.add(days_in_the_week);
    // ...
```

In conclusion:
```rust
    // ...

    let mut conclusion =
        Json::OBJECT {
            name: String::from("Conclusion"),

            value: Box::new(
                Json::JSON(Vec::new())
            )
        }
    ;

    conclusion
        .add(
            Json::OBJECT {
                name: String::from("Minimal in my opinion"),

                value: Box::new(
                    Json::BOOL(true)
                )
            }
        )
        .add(
            Json::OBJECT {
                name: String::from("How much I care about your opinion"),

                value: Box::new(
                    Json::NULL
                )
            }
        )
        .add(
            Json::OBJECT {
                name: String::from("Comment"),

                value: Box::new(
                    Json::STRING( String::from(";)") )
                )
            }
        )
    ;

    json.add(conclusion);
    // ...
```

Calling:
```rust
    // ...
    let resulting_json = json.print();
```
will result in a `String` containing:
`{"Greeting":"Hello, world!","Days of the week":{"Total number of days":7,"They are called":["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]},"Conclusion":{"Minimal in my opinion":true,"How much I care about your opinion":null,"Comment":";)"}}`

If you would like the json string in a different format you can easily make your own 'print' function.

## Tutorial (parsing and working with jsons)

Parsing a json value from bytes is even more minimal - at the cost of being more cumbersome. Let's see how we can parse the json we generated above:
```rust
    use json_minimal::*;

    let json = match Json::parse(b"{\"Greeting\":\"Hello, world!\",\"Days of the week\":{\"Total number of days\":7,\"They are called\":[\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\",\"Sunday\"]},\"Conclusion\":{\"Minimal in my opinion\":true,\"How much I care about your opinion\":null,\"Comment\":\";)\"}}") {
        Ok(json) => {
            json
        },
        Err( (position,message) ) => {
            panic!("`{}` at position `{}`!!!");
        }
    }
    // ...
```

Let's first talk about what information is given for a parsing error. As you might expect it is minimal. `position` above is the position were everything went wrong and the `message` will be something like`"Error parsing array."` if, for example, a closing `]` is missing somewhere. Continuing where we left off:
```rust
    // ...
    match json.get("Greeting") {
        Some(json) => {
            match json {
                Json::OBJECT { name: _, value } => {
                    match value.unbox() {
                        Json::STRING(val) => {
                            assert_eq!("Hello, world!",val);
                        },
                        json => {
                            panic!("Expected Json::STRING but found {:?}",json);
                        }
                    }
                },
                json => {
                    panic!("Expected Json::JSON but found {:?}!!!",json)
                }
            }
        },
        None => {
            panic!("Couln't find Greeting. How rude!");
        }
    }
    // ...
```
Unfortunately all of this was necessary because, even though we were able to confirm that `"Greeting"` exists, we had no way of knowing what it really is. It's not over:
```rust 
    // ...
    match json.get("Days of the week") { // Hint: You can also use `get_mut` to aid in editing/creating jsons...
        Some(json) => {
            match json {
                Json::OBJECT { name: _, value } => {
                    match value.unbox() {
                        Json::JSON(values) => {
                            assert_eq!(values.len(),2);

                            match &values[0] {
                                Json::OBJECT { name, value: _ } => {
                                    assert_eq!("Total number of days",name);
                                },
                                json => {
                                    panic!("Expected Json::OBJECT but found {:?}!!!",json);
                                }
                            }

                            match &values[1] {
                                Json::OBJECT { name, value: _ } => {
                                    assert_eq!("They are called",name);
                                },
                                json => {
                                    panic!("Expected Json::OBJECT but found {:?}!!!",json);
                                }
                            }

                        },
                        json => {
                            panic!("Expected Json::JSON but found {:?}!!!",json);
                        }
                    }
                },
                json => {
                    panic!("Expected Json::OBJECT but found {:?}!!!",json);
                }
            }
        },
        None => {
            panic!("Days of the week not found!");
        }
    }
    // You get the idea.
```
The function `Json::parse(...)` can also parse 'standalone values'. Example:

```rust
    match Json::parse("\"What's up?\"") {
        Ok(json) => {
            match json {
                Json::STRING(val) => {
                    assert_eq!("What's up?",val);
                },
                json => {
                    panic!("Expected Json::STRING but found {:?}!!!",json);
                }
            }
        },
        Err( (position,message) ) => {
            panic!("`{}` at position `{}`.");
        }
    }

    // Another example:

    match Json::parse("[1,2,3,\"four\"]") {
        Ok(json) => {
            match json {
                Json::ARRAY(val) => {
                    assert_eq!(val.len(),4);
                },
                json => {
                    panic!("Expected Json::ARRAY but found {:?}!!!",json);
                }
            }
        },
        Err( (position,message) ) => {
            panic!("`{}` at position `{}`.");
        }
    }
```
## Changes & Improvements

* Lonami (github) has made improvements: 
    1. `json_minimal` can now parse non-ASCII strings and escape sequences. (I overlooked this, I admit.)
    2. The code is cleaner thanks to the question-mark operator and using rustfmt.
    3. Some parsing stuff that didn't work now works.
    
    A thousand thanks to Lonami !!! 

* `json_minimal` can now also parse 'pretty' json like this (as long as only `\r`, `\n`, `\t` and whitespace were used for formatting):
```
{
    "Array": [ "Hello" , "World" , "!" ]
}
```
This should also have worked from the start but I did not include because it of my aversion to energy inefficiency (although it is, perhaps, unfounded).

---
Please let me know if something doesn't work. I can't promise i'll react immediately, though.