Class JsonWriter

  • All Implemented Interfaces:
    Closeable, Flushable, AutoCloseable

    public class JsonWriter
    extends Object
    implements Closeable, Flushable
    Output a Java object graph in JSON format. This code handles cyclic references and can serialize any Object graph without requiring a class to be 'Serializeable' or have any specific methods on it.
    • Call the static method: JsonWriter.objectToJson(employee). This will convert the passed in 'employee' instance into a JSON String.
    • Using streams:
           JsonWriter writer = new JsonWriter(stream);
           writer.write(employee);
           writer.close();
      This will write the 'employee' object to the passed in OutputStream.

    That's it. This can be used as a debugging tool. Output an object graph using the above code. Use the JsonWriter PRETTY_PRINT option to format the the JSON to be human readable.

    This will output any object graph deeply (or null). Object references are properly handled. For example, if you had A->B, B->C, and C->A, then A will be serialized with a B object in it, B will be serialized with a C object in it, and then C will be serialized with a reference to A (ref), not a redefinition of A.


    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

    http://www.apache.org/licenses/LICENSE-2.0

    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.
    • Field Detail

      • CUSTOM_WRITER_MAP

        public static final String CUSTOM_WRITER_MAP
        If set, this maps class ==> CustomWriter
        See Also:
        Constant Field Values
      • NOT_CUSTOM_WRITER_MAP

        public static final String NOT_CUSTOM_WRITER_MAP
        If set, this maps class ==> CustomWriter
        See Also:
        Constant Field Values
      • DATE_FORMAT

        public static final String DATE_FORMAT
        Set the date format to use within the JSON output
        See Also:
        Constant Field Values
      • ISO_DATE_TIME_FORMAT

        public static final String ISO_DATE_TIME_FORMAT
        Constant for use as DATE_FORMAT value
        See Also:
        Constant Field Values
      • FIELD_SPECIFIERS

        public static final String FIELD_SPECIFIERS
        Set value to a Map> which will be used to control which fields on a class are output
        See Also:
        Constant Field Values
      • FIELD_NAME_BLACK_LIST

        public static final String FIELD_NAME_BLACK_LIST
        Set value to a Map> which will be used to control which fields on a class are not output. Black list has always priority to FIELD_SPECIFIERS
        See Also:
        Constant Field Values
      • ENUM_PUBLIC_ONLY

        public static final String ENUM_PUBLIC_ONLY
        If set, indicates that private variables of ENUMs are not to be serialized
        See Also:
        Constant Field Values
      • WRITE_LONGS_AS_STRINGS

        public static final String WRITE_LONGS_AS_STRINGS
        If set, longs are written in quotes (Javascript safe)
        See Also:
        Constant Field Values
      • TYPE_NAME_MAP

        public static final String TYPE_NAME_MAP
        If set, this map will be used when writing @type values - allows short-hand abbreviations type names
        See Also:
        Constant Field Values
      • SHORT_META_KEYS

        public static final String SHORT_META_KEYS
        If set, then @type -> @t, @keys -> @k, @items -> @i
        See Also:
        Constant Field Values
      • FORCE_MAP_FORMAT_ARRAY_KEYS_ITEMS

        public static final String FORCE_MAP_FORMAT_ARRAY_KEYS_ITEMS
        If set to true all maps are transferred to the format @keys[],@items[] regardless of the key_type
        See Also:
        Constant Field Values
    • Constructor Detail

      • JsonWriter

        public JsonWriter​(OutputStream out,
                          Map<String,​Object> optionalArgs)
        Parameters:
        out - OutputStream to which the JSON output will be written.
        optionalArgs - (optional) Map of extra arguments indicating how dates are formatted, what fields are written out (optional). For Date parameters, use the public static DATE_TIME key, and then use the ISO_DATE or ISO_DATE_TIME indicators. Or you can specify your own custom SimpleDateFormat String, or you can associate a SimpleDateFormat object, in which case it will be used. This setting is for both java.util.Date and java.sql.Date. If the DATE_FORMAT key is not used, then dates will be formatted as longs. This long can be turned back into a date by using 'new Date(longValue)'.
    • Method Detail

      • isAllowNanAndInfinity

        public static boolean isAllowNanAndInfinity()
        Returns:
        boolean the allowsNanAndInifnity flag
      • setAllowNanAndInfinity

        public static void setAllowNanAndInfinity​(boolean lenient)
        Set the writer to be out of RFC 4627: it will accept "NaN", "-Infinity" and "Infinity" values.
        Parameters:
        lenient - boolean true allows Nan and Inifinity, -Infinity to be used within JSON.
      • getObjectsReferenced

        public Map getObjectsReferenced()
        Provide access to subclasses.
        Returns:
        Map containing all objects that were referenced within input object graph.
      • getObjectsVisited

        public Map getObjectsVisited()
        Provide access to subclasses.
        Returns:
        Map containing all objects that were visited within input object graph
      • getSubstituteTypeNameIfExists

        protected String getSubstituteTypeNameIfExists​(String typeName)
        Used internally to substitute type names. For example, 'java.util.ArrayList, could have a substitute type name of 'alist'. Set substitute type names using the TYPE_NAME_MAP option.
        Parameters:
        typeName - String name of type to substitute.
        Returns:
        String substituted name, or null if there is no substitute.
      • getSubstituteTypeName

        protected String getSubstituteTypeName​(String typeName)
        Used internally to substitute type names. For example, 'java.util.ArrayList, could have a substitute type name of 'alist'. Set substitute type names using the TYPE_NAME_MAP option.
        Parameters:
        typeName - String name of type to substitute.
        Returns:
        String substituted type name.
      • objectToJson

        public static String objectToJson​(Object item)
        Parameters:
        item - Object (root) to serialized to JSON String.
        Returns:
        String of JSON format representing complete object graph rooted by item.
        See Also:
        objectToJson(Object, java.util.Map)
      • objectToJson

        public static String objectToJson​(Object item,
                                          Map<String,​Object> optionalArgs)
        Convert a Java Object to a JSON String.
        Parameters:
        item - Object to convert to a JSON String.
        optionalArgs - (optional) Map of extra arguments indicating how dates are formatted, what fields are written out (optional). For Date parameters, use the public static DATE_TIME key, and then use the ISO_DATE or ISO_DATE_TIME indicators. Or you can specify your own custom SimpleDateFormat String, or you can associate a SimpleDateFormat object, in which case it will be used. This setting is for both java.util.Date and java.sql.Date. If the DATE_FORMAT key is not used, then dates will be formatted as longs. This long can be turned back into a date by using 'new Date(longValue)'.
        Returns:
        String containing JSON representation of passed in object root.
      • formatJson

        public static String formatJson​(String json)
        Format the passed in JSON string in a nice, human readable format.
        Parameters:
        json - String input JSON
        Returns:
        String containing equivalent JSON, formatted nicely for human readability.
      • formatJson

        public static String formatJson​(String json,
                                        Map readingArgs,
                                        Map writingArgs)
        Format the passed in JSON string in a nice, human readable format.
        Parameters:
        json - String input JSON
        readingArgs - (optional) Map of extra arguments for parsing json. Can be null.
        writingArgs - (optional) Map of extra arguments for writing out json. Can be null.
        Returns:
        String containing equivalent JSON, formatted nicely for human readability.
      • writeIfMatching

        public boolean writeIfMatching​(Object o,
                                       boolean showType,
                                       Writer output)
        Write the passed in object (o) to the JSON output stream, if and only if, there is a custom writer associated to the Class of object (o).
        Parameters:
        o - Object to be (potentially written)
        showType - boolean indicating whether or not to show @type.
        output - Writer where the actual JSON is being written to.
        Returns:
        boolean true if written, false is there is no custom writer for the passed in object.
      • writeArrayElementIfMatching

        public boolean writeArrayElementIfMatching​(Class arrayComponentClass,
                                                   Object o,
                                                   boolean showType,
                                                   Writer output)
        Write the passed in array element to the JSON output, if any only if, there is a customer writer for the class of the instance 'o'.
        Parameters:
        arrayComponentClass - Class type of the array
        o - Object instance to write
        showType - boolean indicating whether or not @type should be output.
        output - Writer to write the JSON to (if there is a custom writer for o's Class).
        Returns:
        true if the array element was written, false otherwise.
      • writeCustom

        protected boolean writeCustom​(Class arrayComponentClass,
                                      Object o,
                                      boolean showType,
                                      Writer output)
                               throws IOException
        Perform the actual custom writing for an array element that has a custom writer.
        Parameters:
        arrayComponentClass - Class type of the array
        o - Object instance to write
        showType - boolean indicating whether or not @type should be output.
        output - Writer to write the JSON to (if there is a custom writer for o's Class).
        Returns:
        true if the array element was written, false otherwise.
        Throws:
        IOException
      • addWriter

        public void addWriter​(Class c,
                              JsonWriter.JsonClassWriterBase writer)
        Add a custom writer which will manage writing objects of the passed in Class in JSON format. The custom writer will be called for objects of the passed in class, including subclasses. If this is not desired, call addNotCustomWriter(c) which will force objects of the passed in Class to be written by the standard JSON writer.
        Parameters:
        c - Class to associate a custom JSON writer too
        writer - JsonClassWriterBase which implements the appropriate subclass of JsonClassWriterBase (JsonClassWriter or JsonClassWriterEx).
      • addWriterPermanent

        public static void addWriterPermanent​(Class c,
                                              JsonWriter.JsonClassWriterBase writer)
        Add a permanent Customer Writer (Lifetime of JVM)
        Parameters:
        c - Class to associate a custom JSON writer too
        writer - JsonClassWriterBase which implements the appropriate subclass of JsonClassWriterBase (JsonClassWriter or JsonClassWriterEx).
      • addNotCustomWriter

        public void addNotCustomWriter​(Class c)
        For no custom writing to occur for the passed in Class.
        Parameters:
        c - Class which should NOT have any custom writer associated to it. Use this to prevent a custom writer from being used due to inheritance.
      • write

        public void write​(Object obj)
        Write the passed in Java object in JSON format.
        Parameters:
        obj - Object any Java Object or JsonObject.
      • traceReferences

        protected void traceReferences​(Object root)
        Walk object graph and visit each instance, following each field, each Collection, Map and so on. Tracks visited to handle cycles and to determine if an item is referenced elsewhere. If an object is never referenced more than once, no @id field needs to be emitted for it.
        Parameters:
        root - Object to be deeply traced. The objVisited and objsReferenced Maps will be written to during the trace.
      • traceFields

        protected void traceFields​(Deque<Object> stack,
                                   Object obj,
                                   Map<Class,​List<Field>> fieldSpecifiers)
        Reach-ability trace to visit all objects within the graph to be written. This API will handle any object, using either reflection APIs or by consulting a specified FIELD_SPECIFIERS map if provided.
        Parameters:
        stack - Deque used to manage descent into graph (rather than using Java stack.) This allows for much larger graph processing.
        obj - Object root of graph
        fieldSpecifiers - Map of optional field specifiers, which are used to override the field list returned by the JDK reflection operations. This allows a subset of the actual fields on an object to be serialized.
      • writeImpl

        public void writeImpl​(Object obj,
                              boolean showType)
                       throws IOException
        Main entry point (mostly used internally, but may be called from a Custom JSON writer). This method will write out whatever object type it is given, including JsonObject's. It will handle null, detecting if a custom writer should be called, array, array of JsonObject, Map, Map of JsonObjects, Collection, Collection of JsonObject, any regular object, or a JsonObject representing a regular object.
        Parameters:
        obj - Object to be written
        showType - if set to true, the @type tag will be output. If false, it will be dropped.
        Throws:
        IOException - if one occurs on the underlying output stream.
      • writeImpl

        public void writeImpl​(Object obj,
                              boolean showType,
                              boolean allowRef,
                              boolean allowCustom)
                       throws IOException
        Main entry point (mostly used internally, but may be called from a Custom JSON writer). This method will write out whatever object type it is given, including JsonObject's. It will handle null, detecting if a custom writer should be called, array, array of JsonObject, Map, Map of JsonObjects, Collection, Collection of JsonObject, any regular object, or a JsonObject representing a regular object.
        Parameters:
        obj - Object to be written
        showType - if set to true, the @type tag will be output. If false, it will be
        allowRef - if set to true, @ref will be used, otherwise 2+ occurrence will be output as full object.
        allowCustom - if set to true, the object being called will allowed to be checked for a matching custom writer to be used. This does not affect subobjects, just the top-level 'obj' being passed in.
        Throws:
        IOException - if one occurs on the underlying output stream.
      • ensureJsonPrimitiveKeys

        public static boolean ensureJsonPrimitiveKeys​(Map map)
        Ensure that all keys within the Map are String instances
        Parameters:
        map - Map to inspect that all keys are primitive. This allows the output JSON to be optimized into {"key1":value1, "key2": value2} format if all the keys of the Map are Strings. If not, then a Map is written as two arrays, an @keys array and an @items array. This allows support for Maps with non-String keys.
      • writeObject

        public void writeObject​(Object obj,
                                boolean showType,
                                boolean bodyOnly)
                         throws IOException
        Parameters:
        obj - Object to be written in JSON format
        showType - boolean true means show the "@type" field, false eliminates it. Many times the type can be dropped because it can be inferred from the field or array type.
        bodyOnly - write only the body of the object
        Throws:
        IOException - if an error occurs writing to the output stream.
      • writeJsonUtf8String

        public static void writeJsonUtf8String​(String s,
                                               Writer output)
                                        throws IOException
        Write out special characters "\b, \f, \t, \n, \r", as such, backslash as \\ quote as \" and values less than an ASCII space (20hex) as "\\u00xx" format, characters in the range of ASCII space to a '~' as ASCII, and anything higher in UTF-8.
        Parameters:
        s - String to be written in UTF-8 format on the output stream.
        output - Writer to which the UTF-8 string will be written to
        Throws:
        IOException - if an error occurs writing to the output stream.
      • flush

        public void flush()
        Specified by:
        flush in interface Flushable