json-streaming 1.0.0

a library for reading and writing JSON from / to a stream without the need to materialize the data in memory. Provides both blocking and async APIs.
Documentation
# json-streaming - reading and writing JSON in a streaming fashion

> This is a library for writing and reading JSON through a streaming API, i.e. without data structures
> that are then "mapped".

It fills a niche: for most typical use cases, the `serde` ecosystem is the better and more natural choice, and if
`serde` does what you need, you should probably choose it over `json-streaming`. This library is written to cover
special use cases:
* Writing and processing big data structures without materializing them
* Writing and reading JSON representations that have significant structural differences to the in-memory representation,
   e.g. flattening nested in-memory maps to a flat JSON object based on domain knowledge
* Fine-grained control over how JSON is written
* Working with JSON in a `no-std`, no-alloc environment

All APIs exist in both blocking and non-blocking variants.

## Getting started

Here's a simple example of how to write JSON using the library:

```
use json_streaming::blocking::*;

fn write_something() -> std::io::Result<()> {
    let mut stdout = std::io::stdout();
    let mut writer = JsonWriter::new_pretty(&mut stdout);

    let mut o = JsonObject::new(&mut writer)?;
    o.write_string_value("a", "hello")?;
    o.write_string_value("b", "world")?;
    o.end()?;

    writer.flush()
}
```

Or reading the same data:
```
use json_streaming::blocking::*;

fn read_something(r: &mut impl io::Read) -> JsonParseResult<(), io::Error> {
    let mut json_reader = JsonReader::new(1024, r);

    json_reader.expect_next_start_object()?;
    loop {
        match json_reader.expect_next_key()? {
            Some("a") => println!("a: {}", json_reader.expect_next_string()?),
            Some("b") => println!("b: {}", json_reader.expect_next_string()?),
            Some(_other) => {
                return Err(JsonParseError::Parse("unexpected key parsing 'person'", json_reader.location()));
            },
            None => break,
        }
    }
    Ok(())
}
```

See the examples (`blocking.rs` and `non_blocking.rs` are good starting points) for more comprehensive code with
lots of comments to explain.

## Feature Flags

### default

By default, both blocking and non-blocking APIs are included. Adapters to `std::io::Read` and `std::io::Write` are
included, making the default library depend on `std` by default. 

The `tokio` adapters for non-blocking APIs are not included and require the `tokio` feature flag. This is done to 
avoid pulling in the `tokio` dependency by default.

> default = ["blocking", "non-blocking", "std"]

### blocking and std

The `blocking` feature flag is active by default; for detailed control, `default-features` must be disabled. The
`blocking` feature flag by itself adds the blocking APIs themselves (which do *not* depend on *std*), but not the adapters
for `std::io::Read` and `std::io::Write` (which do).

So in order to work with JSON in a `no-std` environment, disable `default-features` and add the `blocking` feature
flag. You will have to provide your own implementations of the `BlockingRead` or `BlockingWrite` trait to adapt to
your environment's data sources or sinks. See the `no_std.rs` example for a showcase.

### non-blocking and tokio

The non-blocking API is included by default, but without the adapters for Tokio's `tokio::io::AsyncRead` and 
`tokio::io::AsyncWrite` traits - those require the `tokio` feature flag, which adds a dependency on the Tokio library.