Class JsonReader

java.lang.Object
com.cedarsoftware.io.JsonReader
All Implemented Interfaces:
Closeable, AutoCloseable

public class JsonReader extends Object implements Closeable
Read an object graph in JSON format and make it available in Java objects, or in a "Map of Maps." (untyped representation). This code handles cyclic references and can deserialize any Object graph without requiring a class to be 'Serializable' or have any specific methods on it. It will handle classes with non-public constructors.

Usages:
  • Call the static method: JsonReader.jsonToJava(String json). This will return a typed Java object graph.
  • Call the static method: JsonReader.jsonToMaps(String json). This will return an untyped object representation of the JSON String as a Map of Maps, where the fields are the Map keys, and the field values are the associated Map's values. You can call the JsonWriter.objectToJson() method with the returned Map, and it will serialize the Graph into the equivalent JSON stream from which it was read.
  • Instantiate the JsonReader with an InputStream: JsonReader(InputStream in) and then call readObject(). Cast the return value of readObject() to the Java class that was the root of the graph.
  • Instantiate the JsonReader with an InputStream: JsonReader(InputStream in, true) and then call readObject(). The return value will be a Map of Maps.

Author:
John DeRegnaucourt ([email protected])
Copyright (c) Cedar Software LLC

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

License

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  • Constructor Details

    • JsonReader

      public JsonReader(InputStream input, ReadOptions readOptions)
      Creates a json reader using custom read options
      Parameters:
      input - InputStream of utf-encoded json
      readOptions - Read Options to turn on/off various feature options, or supply additional ClassFactory data, etc. If null, readOptions will use all defaults.
    • JsonReader

      public JsonReader(InputStream inputStream, ReadOptions readOptions, ReferenceTracker references)
    • JsonReader

      public JsonReader(ReadOptions readOptions)
      Use this constructor if you already have a JsonObject graph and want to parse it into Java objects by calling jsonReader.jsonObjectsToJava(rootJsonObject) after constructing the JsonReader.
      Parameters:
      readOptions - Read Options to turn on/off various feature options, or supply additional ClassFactory data, etc. If null, readOptions will use all defaults.
    • JsonReader

      public JsonReader(Resolver resolver)
      Use this constructor to resolve JsonObjects into Java, for example, in a ClassFactory or custom reader. Then use jsonReader.jsonObjectsToJava(rootJsonObject) to turn JsonObject graph (sub-graph) into Java.
      Parameters:
      resolver - Resolver, obtained from ClassFactory.newInstance() or CustomReader.read().
  • Method Details

    • getReader

      protected com.cedarsoftware.util.FastReader getReader(InputStream inputStream)
      Allow others to try potentially faster Readers.
      Parameters:
      inputStream - InputStream that will be offering JSON.
      Returns:
      FastReader wrapped around the passed in inputStream, translating from InputStream to InputStreamReader.
    • readObject

      public <T> T readObject(Type rootType)
      Reads and parses a JSON structure from the underlying parser, then returns an object of type T. The parsing and return type resolution follow these steps:
      • Attempts to parse the top-level JSON element (e.g. object, array, or primitive) and produce an initial returnValue of type T (as inferred or declared).
      • If the parsed value is null, simply returns null.
      • If the value is recognized as an “array-like” structure (either an actual Java array or a JsonObject flagged as an array), it delegates to handleArrayRoot() to build the final result object.
      • If the value is a JsonObject at the root, it delegates to determineReturnValueWhenJsonObjectRoot() for further resolution.
      • Otherwise (if it’s a primitive or other type), it may convert the result to rootType if needed/possible.
      Type Parameters:
      T - The expected return type.
      Parameters:
      rootType - The class token representing the desired return type. May be null, in which case the type is inferred from the JSON content or defaults to the parser’s best guess.
      Returns:
      The fully resolved and (if applicable) type-converted object. Could be null if the JSON explicitly represents a null value.
      Throws:
      JsonIoException - if there is any error parsing or resolving the JSON content, or if type conversion fails (e.g., when the actual type does not match the requested rootType and no valid conversion is available).
    • toJava

      public Object toJava(Type rootType, Object root)
      Only use from ClassFactory or CustomReader
    • resolveObjects

      protected <T> T resolveObjects(JsonObject rootObj, Type rootType)
      Deserializes a JSON object graph into a strongly-typed Java object instance.

      This method processes a root JsonObject that represents the serialized form of a Java object graph, which may include nested Map instances and other complex structures. It converts this JSON-based representation back into a typed Java object, optionally guided by the specified rootType.

      If the rootType parameter is null, the method attempts to infer the appropriate Java class from the @type annotation within the rootObj. In the absence of such type information, it defaults to Object.

      After the deserialization process, the method ensures that the resolver's state is cleaned up, maintaining the integrity of subsequent operations.

      Type Parameters:
      T - the expected type of the Java object to be returned
      Parameters:
      rootObj - the root JsonObject representing the serialized JSON object graph to be deserialized
      rootType - the desired Java type for the root object. If null, the method will attempt to determine the type from the @type annotation in rootObj
      Returns:
      a Java object instance corresponding to the provided JSON graph, of type T
      Throws:
      JsonIoException - if an error occurs during deserialization, such as type conversion issues or I/O errors

      Implementation Notes:

      • When rootType is null, the method prioritizes type inference from the @type annotation within rootObj. If no type information is available, it defaults to Object.
      • If ReadOptions.isCloseStream() is true, the method ensures that the associated stream is closed upon encountering an exception to prevent resource leaks.
      • Post-deserialization, the resolver's state is cleaned up to maintain consistency and prevent interference with subsequent deserialization operations.
      Implementation Note:

      This method is designed to handle both scenarios where type information is provided and where it is absent. It ensures robust deserialization by falling back to generic types when necessary and by leveraging type conversion mappings defined within the converter.

    • getResolver

      public Resolver getResolver()
      Returns the current Resolver instance used for JSON deserialization.

      The Resolver serves as the superclass for both ObjectResolver and MapResolver, each handling specific aspects of converting JSON structures into Java objects.

      • ObjectResolver:

        Responsible for converting JSON maps (represented by JsonObject) into their corresponding Java object instances. It handles the instantiation of Java classes and populates their fields based on the JSON data.

      • MapResolver:

        Focuses on refining the value side within a map. It utilizes the class information associated with a JsonObject to coerce primitive fields in the map's values to their correct data types. For example, if a Long is serialized as a String in the JSON, the MapResolver will convert it back to a Long within the map by matching the JSON key to the corresponding field in the Java class and transforming the raw JSON primitive value to the field's type (e.g., long/Long).

      This method is essential for scenarios where JSON data needs to be deserialized into Java objects, ensuring that both object instantiation and type coercion are handled appropriately.

      Returns:
      the Resolver currently in use. This Resolver is the superclass for ObjectResolver and MapResolver, facilitating the conversion of JSON structures into Java objects and the coercion of map values to their correct data types.
    • close

      public void close()
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable