de.caff.io.json

## Class SimpleJsonReader

- java.lang.Object
- - de.caff.io.json.SimpleJsonReader

-     public class SimpleJsonReader
      extends java.lang.Object

  Simple JSON reader.

  This provides a very basic way to read JSON following RFC 8259.

  JSON data is decomposed into a stream of simple events which are handled by a user-defined handler which reacts on values or starting of objects and arrays.

  Because of the recursive nature of JSON handlers may apply sub-handlers by means of pushSubHandler(Handler) and popSubHandler(). There is no automatic popping, so user code has to take care to pop handlers whenever necessary. The current environment type can be requested with the method getEnvironment(). When requested inside `SimpleJsonReader.Handler.beginObject(SimpleJsonReader)`, `SimpleJsonReader.Handler.endObject(SimpleJsonReader)`, `SimpleJsonReader.Handler.beginArray(SimpleJsonReader)`, and `SimpleJsonReader.Handler.endArray(SimpleJsonReader)` the reader argument will return the surrounding environment.

  A set of useful default implementations which make use of the above stacking is also provided:

  - `SimpleJsonReader.ObjectHandler`: handle the content of an object. Methods to implement are:
    - `SimpleJsonReader.ObjectHandler.nullValue(String)`: receive null value for the given key
    - `SimpleJsonReader.ObjectHandler.value(String, String)`: receive string value for the given key
    - `SimpleJsonReader.ObjectHandler.value(String, Number)`: receive numeric value for the given key
    - `SimpleJsonReader.ObjectHandler.value(String, boolean)`: receive boolean value for the given key
    - `SimpleJsonReader.ObjectHandler.objectValue(String)`: provide a handler for an object value for the given key
    - `SimpleJsonReader.ObjectHandler.arrayValue(String)`: provide a handler for an array value for the given
  - `SimpleJsonReader.ArrayHandler`: handle the content of an array. Methods to implement are:
    - `SimpleJsonReader.ArrayHandler.nullElement(int)`: receive null value for the given index
    - `SimpleJsonReader.ArrayHandler.element(int, String)`: receive string value for the given index
    - `SimpleJsonReader.ArrayHandler.element(int, Number)`: receive numeric value for the given index
    - `SimpleJsonReader.ArrayHandler.element(int, boolean)`: receive boolean value for the given index
    - `SimpleJsonReader.ObjectHandler.objectValue(String)`: receive provide a handler for an object value for the given key
    - `SimpleJsonReader.ObjectHandler.arrayValue(String)`: receive provide a handler for an array value for the given
  - `SimpleJsonReader.ValueHandler`: this is useful as the starting handler for a complete JSON file. By default it is expected that the content is a JSON object, therefore only one method has to be implemented:
    - `SimpleJsonReader.ValueHandler.object()`: provide a handler (usually an `SimpleJsonReader.ObjectHandler`) for handling the object's content.
    But the handler is prepared to read any valid JSON file, therefore the following methods throw an exception by default, but you can override them to fit your needs:
    - `SimpleJsonReader.ValueHandler.array()`: provide a handler (usually an `SimpleJsonReader.ArrayHandler` for handling the array's content.
    - `SimpleJsonReader.ValueHandler.nullValue()`: receive a null value.
    - `SimpleJsonReader.ValueHandler.value(String)`: receive a string value.
    - `SimpleJsonReader.ValueHandler.value(Number)`: receive a numeric value.
    - `SimpleJsonReader.ValueHandler.value(boolean)`: receive a boolean value.
  Also provided is a method to read a JSON file into a `Map` with string keys which might come handy for simple files: `readToMap(Reader)`. The created map is an exact mirror of the JSON content. Obviously, it requires JSON files which contain a JSON object.
  Since:
    2022/05/01
  Author:
    Rammi

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `SimpleJsonReader.ArrayHandler` Dedicated array handler.
    `static class` | `SimpleJsonReader.BooleanValueHandler` Handler which only accepts a boolean value.
    `static class` | `SimpleJsonReader.DoubleValueHandler` Handler which only accepts a double value.
    `static interface` | `SimpleJsonReader.Handler` Low-level Handler for streamed JSON stream.
    `static class` | `SimpleJsonReader.HandlerWrapper`
    `static class` | `SimpleJsonReader.IntValueHandler` Handler which only accepts an integer value.
    `static class` | `SimpleJsonReader.MapObjectHandler` Map object handler which collects the JSON data into a Java map.
    `static class` | `SimpleJsonReader.NumericValueHandler` Handler which only accepts a numeric value.
    `static class` | `SimpleJsonReader.ObjectHandler`
    `static class` | `SimpleJsonReader.StringValueHandler` Handler which only accepts a string value.
    `static interface` | `SimpleJsonReader.TemporaryHandler`
    `static class` | `SimpleJsonReader.ValueHandler` Handler which just reads a single value.

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static SimpleJsonReader.TemporaryHandler` | `SKIP_HANDLER` Temporary handler which ignores all input.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `Json.Env` | `getEnvironment()` Get the current environment.
    `SimpleJsonReader.Handler` | `getSubHandler()`
    `static void` | `main(java.lang.String[] args)` Test code.
    `SimpleJsonReader.Handler` | `popSubHandler()` Pop a previously pushed sub handler.
    `void` | `pushSubHandler(SimpleJsonReader.Handler handler)` Push a sub handler.
    `static void` | `read(java.io.InputStream is, java.nio.charset.Charset charset, SimpleJsonReader.Handler handler)` Read JSON from an input stream.
    `static void` | `read(java.io.InputStream is, SimpleJsonReader.Handler handler)` Read JSON from an input stream.
    `static void` | `read(java.io.Reader reader, SimpleJsonReader.Handler handler)` Read JSON data from a reader.
    `static java.util.Map<java.lang.String,java.lang.Object>` | `readToMap(java.io.InputStream is)` Read a JSON file into a Java Map, using the UTF-8 charset recommended by RFC 8259.
    `static java.util.Map<java.lang.String,java.lang.Object>` | `readToMap(java.io.InputStream is, java.nio.charset.Charset charset)` Read a JSON file into a Java Map.
    `static java.util.Map<java.lang.String,java.lang.Object>` | `readToMap(java.io.Reader reader)` Read a JSON file into a Java Map.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### SKIP_HANDLER

          public static final SimpleJsonReader.TemporaryHandler SKIP_HANDLER

      Temporary handler which ignores all input.

  - ### Method Detail

    - #### pushSubHandler

          public void pushSubHandler(@NotNull
                                     SimpleJsonReader.Handler handler)

      Push a sub handler. The given sub handler will be used for handling until `popped` or another call to this method happens. Using this method requires handling popping accordingly, this class will not pop anything automatically.
      Parameters:
        `handler` - handler to be pushed

    - #### popSubHandler

          @NotNull
          public SimpleJsonReader.Handler popSubHandler()

      Pop a previously pushed sub handler. This will make the handler which was active before pushing the active handler again.
      Returns:
        the popped handler, allowing user code to do basic checks

    - #### getSubHandler

          @NotNull
          public SimpleJsonReader.Handler getSubHandler()

    - #### getEnvironment

          @Nullable
          public Json.Env getEnvironment()

      Get the current environment.
      Returns:
        environment, or `null` for initial and final state

    - #### read

          public static void read(@NotNull
                                  java.io.Reader reader,
                                  @NotNull
                                  SimpleJsonReader.Handler handler)
                           throws java.io.IOException

      Read JSON data from a reader.
      Parameters:
        `reader` - reader to read from
        `handler` - handler which is called with all JSON items in sequence
      Throws:
        `java.io.IOException` - on read or format errors
      See Also:
        `read(InputStream, Charset, Handler)`, `read(InputStream, Handler)`

    - #### read

          public static void read(@NotNull
                                  java.io.InputStream is,
                                  @NotNull
                                  java.nio.charset.Charset charset,
                                  @NotNull
                                  SimpleJsonReader.Handler handler)
                           throws java.io.IOException

      Read JSON from an input stream.
      Parameters:
        `is` - input stream to read from
        `charset` - charset of the given input stream. Note that RFC 8259 assumes that UTF-8 is uses
        `handler` - handler which is called with all JSON items in sequence
      Throws:
        `java.io.IOException` - on read or format errors
      See Also:
        `read(InputStream, Handler)`, `read(Reader, Handler)`

    - #### read

          public static void read(@NotNull
                                  java.io.InputStream is,
                                  @NotNull
                                  SimpleJsonReader.Handler handler)
                           throws java.io.IOException

      Read JSON from an input stream. This uses `the UTF-8 charset recommended by RFC 8259`.
      Parameters:
        `is` - input stream to read from
        `handler` - handler which is called with all JSON items in sequence
      Throws:
        `java.io.IOException` - on read or format errors
      See Also:
        `read(InputStream, Charset, Handler)`, `read(Reader, Handler)`

    - #### readToMap

          @NotNull
          public static java.util.Map<java.lang.String,java.lang.Object> readToMap(@NotNull
                                                                                            java.io.Reader reader)
                                                                                     throws java.io.IOException

      Read a JSON file into a Java Map. This assumes that the JSON file contains an object, and will throw `IllegalStateException` otherwise.
      Parameters:
        `reader` - reader to read from
      Returns:
        map with String keys with values which are either strings, number, booleans, `null` values, arrays of the above value types (which again can contain any type of element, including arrays and maps), and recursive maps
      Throws:
        `java.io.IOException` - on read or format errors

    - #### readToMap

          @NotNull
          public static java.util.Map<java.lang.String,java.lang.Object> readToMap(@NotNull
                                                                                            java.io.InputStream is,
                                                                                            @NotNull
                                                                                            java.nio.charset.Charset charset)
                                                                                     throws java.io.IOException

      Read a JSON file into a Java Map. This assumes that the JSON file contains an object, and will throw `IllegalStateException` otherwise.
      Parameters:
        `is` - input stream to read from
        `charset` - charset of the given input stream
      Returns:
        map with String keys with values which are either strings, number, booleans, `null` values, arrays of the above value types (which again can contain any type of element, including arrays and maps), and recursive maps
      Throws:
        `java.io.IOException` - on read or format errors

    - #### readToMap

          @NotNull
          public static java.util.Map<java.lang.String,java.lang.Object> readToMap(@NotNull
                                                                                            java.io.InputStream is)
                                                                                     throws java.io.IOException

      Read a JSON file into a Java Map, using the UTF-8 charset recommended by RFC 8259. This assumes that the JSON file contains an object, and will throw `IllegalStateException` otherwise.
      Parameters:
        `is` - input stream to read from
      Returns:
        map with String keys with values which are either strings, number, booleans, `null` values, arrays of the above value types (which again can contain any type of element, including arrays and maps), and recursice maps
      Throws:
        `java.io.IOException` - on read or format errors

    - #### main

          public static void main(@NotNull
                                  java.lang.String[] args)
                           throws java.io.IOException

      Test code.
      Parameters:
        `args` - paths of JSON files
      Throws:
        `java.io.IOException` - on read or format errors