Class ReadJSON


  • public class ReadJSON
    extends java.lang.Object
    JSON Binding Helper-Class:
    JSON-Binding is the art of converting data that has been stored, saved or transmitted using Java-Script Object Notation into a Primitive-Type or Object-Type of any Programming Language, for instance Java. JSON often arrives into Java-Program Memory from an external Internet Connection, and may have traveled hundreds or even thousands of miles from a Host-Server.

    Unlike Java-Types which are checked by the Java-Compiler each-and-every time a programmer compiles his project, any guarantee that JSON-Type Data is pristine, uncorrupted, and in any kind of pre-agreed format is never completely assured.

    Being able to handle changes that might be made to an API (possibly from great distances away, and without the Software-Manager's consent) is the type of feature that robust JSON-Code simply has to offer.

    Binding-Helper Features:
    • Utilizes the Java-Standard javax.json.* Package-Library, & its Glass-Fish Implementation
    • Handles the Transfer & Conversion of All Json-Type's into Java-Type's with just One Line of Code
    • Provides all manner of User-Configurable Exception-Handling & Error-Decision Management via Class JFlag
    • Provides a Fine-Grained Suite of Exception-Classes, all with Consistent & Meaningful Error-Messages
    • Primary Helper-Classes for the (Experimental) Google-Chrome Headless Browser Package
    Builds on the J2EE Standard Release JSON Parsing Tools by providing additional help with converting JSON Data into Java Object-Data.

    This class builds on the J2EE Standard 'Glass-Fish' JSON Processor

    There are several JSON Parsers available, and even more implementations for serializing and de-serializing data to/from JSON. The tool included in the J2EE is available on GitHub, and that is the one used by the Java HTML JAR Library. (See: javax.json.* )

    Primary Classes Used: JsonArray and JsonObject

    The main goal of the methods in these classes is simply to reduce the amount of code that needs to be written by a programmer when writing JSON De-Serializing Methods. For instance, when writing a Java Wrapper around a REST API (like the 'Facebook', 'YouTube', 'IMDB' or 'Twitter' API's), being able to write a constructor for Java Object that essentially needs just one line of code to assign each of the fields in the Java Object makes writing REST API POJO's a lot faster.

    If the JSON that your code is parsing is guaranteed to be free from nulls, missing properties, and incorrect types - then the vast majority of the methods in this class will not provide much additional benefit to your program. If your JSON data is definitively well-known, and well-understood, using the more basic features that are already availabe in the J2EE Json Parser should be enough! The features available in this class are here mainly to simplify handling all possibilities for error and unexpected-input that can happen when transmiting data with JSON.

    Simplicity:
    There are JSON Packages available (for instance the 'Jackson' Suite of Tools) that have hundreds of classes for creating Java-Objects out of JSON Objects. However, their level of complexity (and ubiquitous use of annotations) can be so over-powering, that they sometimes seem unusable.

    Every one of the Java-Objects in the Headless-Browser / Chrome Remote Debugging A.P.I. have objects whose constructor's all use this 'ReadJSON' class to extract the Object Fields from the JSON Properties in just a few lines (Actually, the number of lines of code in each of the constructors in that package is exactly equal to the number of fields in each of the classes there.) For an example of the use of this class, please refer to any of the constructors or the commands inside the browser package.

    Example:
    public class Automobile
    {
        public final String     make;
        public final String     model
        public final short      year;
        public final Integer    miles;   // Boxed-Type "Integer" (capital 'I') ALLOWS NULL!
        public final Boolean    compact; // Boxed-Type "Boolean" (capital 'B') ALLOWS NULL!
    
        public Automobile(JsonObject jo)
        {
            // The "Make" of the care is guaranteed.
            // THROWS: If Property is not available, null, or not a JsonString
    
            this.make = ReadJSON.getString(jo, "Manufacturer");
    
            // The "Model" of the car, isn't guaranteed.
            // THROWS:  Only if the property isn't a JsonString
            // RETURNS: 'null' if it is missing, or set to Json-Null
    
            this.model = ReadJSON.getString(jo, "Model", true, false);
    
            // The "Year" Property is also guaranteed. 
            // THROWS:  If missing, null, wrong-type (on all error cases)
            // RETURNS: The "Year" jo property-value
    
            this.year = ReadPrimJSON.getShort(jo, "Year");
    
            // This is an optional "Miles" Property.
            // THROWS:  No exception is thrown if this property is missing or null
            //          If the property is the wrong-type (not a number), throws JsonTypeObjException
            // RETURNS: miles property-value, or the default-Value of '0' (if missing or null)
    
            this.miles = ReadBoxedJSON.getInteger(jo, "miles", RD_N | RD_M, 0);
        
            // Optional "compact" boolean property.
            // THROWS:  NEVER - even if missing, null, or not a Json-Boolean.
            // RETURNS: 'isCompact' property-value *or* auto-assigns null on error
    
            this.compact = ReadBoxedJSON.getBoolean(jo, "isCompact", RETURN_NULL_ON_ANY_ALL, false);
        }
    
        public static void main(String[] argv) throws Exception
        {
            // Read and load JSON into a String, then to a 'JsonObject'
            String          json    = FileRW.loadFileToString("some-file.json");
            StringReader    sr      = new StringReader(json);
            JsonObject      jo      = Json.createReader(sr).readObject();
    
            // Build an "Automobile" Object instance
            Automobile auto = new Automobile(jo);
        }
    }
    

    POJO De-Serialization:
    The methods that appear to de-serialize a JSON Object into a standard Java-Object require a constructor that accepts a JsonObject. Automatic type-creation (as exists in libraries such as 'Lombok') is not an feature offered by this class. There is not a lot of "magic", however these methods can reduce a lot of the work needed to convert Json into Java through field initializations that have been reduced to nothing more than a single line of code.

    The primary value of the FLAGS configuration-parameters and other assorted boolean-parameters are just to ensure that if / when erroneous JSON is received from a REST Web-Service, that it is instantly and automatically handled appropriately. Dealing with such erroneous input can be accomplished through default-values, exception-throws or null-values.

    The exception messages provided by this package are extremely readable, and contain al the information needed when debugging REST-API interfaces.
    See Also:
    Json, JsonObject, JsonArray



    Stateless Class:
    This class neither contains any program-state, nor can it be instantiated. The @StaticFunctional Annotation may also be called 'The Spaghetti Report'. Static-Functional classes are, essentially, C-Styled Files, without any constructors or non-static member fields. It is a concept very similar to the Java-Bean's @Stateless Annotation.

    • 1 Constructor(s), 1 declared private, zero-argument constructor
    • 5 Method(s), 5 declared static
    • 0 Field(s)


    • Method Summary

       
      Object: Retrieve a JsonObject and transform it to a Java Object
      Modifier and Type Method
      static <T> T getObject​(JsonArray ja, int index, Class<T> c, boolean throwOnNull)
      static <T> T getObject​(JsonObject jo, Class<T> c)
      static <T> T getObject​(JsonObject jo, String propertyName, Class<T> c, boolean isOptional, boolean throwOnNull)
       
      String: Retrieve a JsonString and transform it to a Java String
      Modifier and Type Method
      static String getString​(JsonArray ja, int index, boolean throwOnNull)
      static String getString​(JsonObject jo, String propertyName, boolean isOptional, boolean throwOnNull)
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • getObject

        🡇     🗕  🗗  🗖
        public static <T> T getObject​(JsonArray ja,
                                      int index,
                                      java.lang.Class<T> c,
                                      boolean throwOnNull)
        Retrieve a JsonArray element, and transform it to a Java Object (POJO).
        Type Parameters:
        T - This is the Java-Type to which the JsonObject is going to be bound / transformed.

        It is important to note that this method is not as smart as you might think. The Java-Type instance that is being created / instantiated must contain a consructor that accepts a JsonObject as a parameter in order to do the actual bindng. specifically, whatever class is passed to type parameter 'T', that class must have a single-parameter constructor whose parameter-type is JsonObject
        Parameters:
        ja - Any instance of JsonArray
        index - A valid index into array parameter 'ja'. In Json (and unlike Java), array element types are not actually checked for consistency - meaning an array may hold many different types! This array-index must contain a JsonObject
        c - This is the class that will bind to the JsonObject parameter 'jo'.

        IMPORTANT: The class 'c' must have a a constructor that accepts a JsonObject. If this class doesn't have such a constructor, then a JsonBindingException throws.
        throwOnNull - When TRUE is passed to this parameter, if the JsonArray element located at 'index' contains Json-Null, then this method will throw a JsonNullArrException. When this parameter is FALSE, if the specified array element contains Json-Null, then Java-Null is returned.
        Returns:
        An instance of Java-Type Type Parameter T, if the 'ja' array element located at 'index' uses the appropriate Json-Type - JsonObject.

        If the specified array element contains Json-Null, and 'throwOnNull' has been passed FALSE, then Java-Null is returned. If the element is null, and 'throwOnNull' is TRUE, then a JsonNullArrException throws.
        Throws:
        java.lang.IndexOutOfBoundsException - If 'index' is out of bounds of 'ja'
        JsonTypeArrException - If the array-element (specified by 'index') does not actually contain a JsonObject (but rather, some other non-null Json-Type), then this exception throws.
        JsonNullArrException - If the JsonArray element specified by 'index' contains a Json-Null, and TRUE has been passed to 'throwOnNull'
        JsonException - If any of the Java reflection-operations throw exceptions, those exceptions are wrapped into a JsonException instance, and then re-thrown with the original exception assigned to the Throwable.cause. Class JsonException is an unchecked / Runtime exception, while many of the cause exceptions are not. The possible cause exceptions are listed below.

        Description copied from: java.lang.Constructor.newInstance(Object... args), JDK 1.8
        ExceptionJDK Explanation
        IllegalAccessException if this Constructor object is enforcing Java language access control and the underlying constructor is inaccessible.
        IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if this constructor pertains to an enum type.
        InstantiationException if the class that declares the underlying constructor represents an abstract class.
        InvocationTargetException if the underlying constructor throws an exception.
        ExceptionInInitializerError if the initialization provoked by this method fails.
        Code:
        Exact Method Body:
         // This will throw an IndexOutOfBoundsException if the index is out of bounds.
         JsonValue jv = ja.get(index);
        
         switch (jv.getValueType())
         {
             case NULL:
        
                 // This is simple-stuff (not rocket-science).  "Type Mapping" Code has to worry
                 // about what the meaning of "null" should be.
        
                 if (throwOnNull) throw new JsonNullArrException(ja, index, OBJECT, c);
                 else return getObject(null, c);
        
             case OBJECT: return getObject((JsonObject) jv, c);
        
             // The JsonValue at the specified array-index does not contain a JsonObject.
             default: throw new JsonTypeArrException(ja, index, OBJECT, jv, c);
         }
        
      • getObject

        🡅  🡇     🗕  🗗  🗖
        public static <T> T getObject​(JsonObject jo,
                                      java.lang.String propertyName,
                                      java.lang.Class<T> c,
                                      boolean isOptional,
                                      boolean throwOnNull)
        Extract a JsonObject property, and transform it to a Java Object (POJO).
        Type Parameters:
        T - This is the Java-Type to which the JsonObject is going to be bound / transformed.

        It is important to note that this method is not as smart as you might think. The Java-Type instance that is being created / instantiated must contain a consructor that accepts a JsonObject as a parameter in order to do the actual bindng. specifically, whatever class is passed to type parameter 'T', that class must have a single-parameter constructor whose parameter-type is JsonObject
        Parameters:
        jo - Any instance of JsonObject.
        propertyName - The name of the JSON property that should be contained within 'jo'. This property will be retrieved and subsequently transformed / converted to Java-Type Type Parameter T.
        isOptional - When TRUE is passed, if 'propertyName' is not actually listed in 'jo' this method shall return Java-Null gracefully. When FALSE is passed, if 'jo' does not have the specified property, a JsonPropMissingException will throw.

        If 'jo' actually has a property named 'propertyName', then the value passed to this parameter is fully irrelevant.
        throwOnNull - When TRUE is passed to this parameter, if the JsonObject property named 'propertyName' evaluates to Json-Null, then this method will throw a JsonNullObjException. When this parameter is FALSE, if the specified property contains Json-Null, then Java-Null is returned.
        Returns:
        An instance of Java-Type Type Parameter T', if the 'propertyName' is available inside 'jo', and that property uses the appropriate Json-Type - JsonObject.

        If the specified property contains Json-Null, and 'throwOnNull' has been passed FALSE, then Java-Null is returned. If the property is null, and 'throwOnNull' is TRUE, then a JsonNullObjException throws.

        If the specified property is simply missing, Java-Null is returned, unless 'isOptional' has been passed FALSE - in which case a JsonPropMissingException shall be thrown.
        Throws:
        JsonPropMissingException - This exception shall throw if the specified property is missing from the 'JsonObject' (parameter 'jo'). This exception throw can be avoided if 'TRUE' is passed to parameter 'isOptional'.
        JsonTypeObjException - If the property (specified by 'propertyName') is extracted, but that property does not actually contain a JsonObject (but rather, some other non-null Json-Type), then this exception throws.
        JsonNullObjException - If the JsonObject property specified by 'propertyName' contains a Json-Null, and TRUE has been passed to 'throwOnNull'
        JsonException - If any of the Java reflection-operations throw exceptions, those exceptions are wrapped into a JsonException instance, and then re-thrown with the original exception assigned to the Throwable.cause. Class JsonException is an unchecked / Runtime exception, while many of the cause exceptions are not. The possible cause exceptions are listed below.

        Description copied from: java.lang.Constructor.newInstance(Object... args), JDK 1.8
        ExceptionJDK Explanation
        IllegalAccessException if this Constructor object is enforcing Java language access control and the underlying constructor is inaccessible.
        IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if this constructor pertains to an enum type.
        InstantiationException if the class that declares the underlying constructor represents an abstract class.
        InvocationTargetException if the underlying constructor throws an exception.
        ExceptionInInitializerError if the initialization provoked by this method fails.
        Code:
        Exact Method Body:
         if (! jo.containsKey(propertyName))
         {
             if (isOptional) return null;
        
             throw new JsonPropMissingException(jo, propertyName, OBJECT, c);
         }
        
         JsonValue jv = jo.get(propertyName);
        
         switch (jv.getValueType())
         {
             case NULL:
        
                 // This is simple-stuff (not rocket-science).  "Type Mapping" Code has to
                 // worry about what the meaning of "null" should be.
        
                 if (throwOnNull) throw new JsonNullObjException(jo, propertyName, OBJECT, c);
        
                 return getObject(null, c);
        
             case OBJECT: return getObject((JsonObject) jv, c);
        
                 // The JsonObject propertydoes not contain a JsonObject.
             default: throw new JsonTypeObjException(jo, propertyName, OBJECT, jv, c);
         }
        
      • getObject

        🡅  🡇     🗕  🗗  🗖
        public static <T> T getObject​(JsonObject jo,
                                      java.lang.Class<T> c)
        This class contains a lot of the reason / impetus for writing 'ReadJSON'. This does converts a JsonObject into a Java-Object. The actual binding must be implemented by the programmer - because the class-type that is passed to this method (parameter 'c') must have a constructor accepting this JsonObject.

        No Auto-Mapping:
        This method makes no effort to figure out which JsonObject properties should be bound to the POJO Object fields! Note, however, that all of the other one-line type conversion methods in this class is exactly why writing such a constuctor for your Java-Type's should be much easier.

        That really is the point of this JSON Package.
        Type Parameters:
        T - This is the Java-Type to which the JsonObject is going to be bound / transformed.

        It is important to note that this method is not as smart as you might think. The Java-Type instance that is being created / instantiated must contain a consructor that accepts a JsonObject as a parameter in order to do the actual bindng. specifically, whatever class is passed to type parameter 'T', that class must have a single-parameter constructor whose parameter-type is JsonObject
        Parameters:
        jo - This may be any JsonObject which can be bound to 'c'.

        NOTE: This parameter may be null, and if it is, null is passed to the 'c' constructor.
        c - This is the class that will bind to the JsonObject parameter 'jo'.

        IMPORTANT: The class 'c' must have a a constructor that accepts a JsonObject. If this class doesn't have such a constructor, then a JsonBindingException throws.
        Returns:
        An instance of the class 'T', which is specified by 'c'
        Throws:
        JsonException - If any of the Java reflection-operations throw exceptions, those exceptions are wrapped into a JsonException instance, and then re-thrown with the original exception assigned to the Throwable.cause. Class JsonException is an unchecked / Runtime exception, while many of the cause exceptions are not. The possible cause exceptions are listed below.

        Description copied from: java.lang.Constructor.newInstance(Object... args), JDK 1.8
        ExceptionJDK Explanation
        IllegalAccessException if this Constructor object is enforcing Java language access control and the underlying constructor is inaccessible.
        IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if this constructor pertains to an enum type.
        InstantiationException if the class that declares the underlying constructor represents an abstract class.
        InvocationTargetException if the underlying constructor throws an exception.
        ExceptionInInitializerError if the initialization provoked by this method fails.
        Code:
        Exact Method Body:
         Constructor<T> ctor = null;
        
         try
         {
             // This just gets a "Constructor" using Reflection.  The main point is that the
             // Constructor must have exactly one parameter - and that parameter must have a
             // type "JsonObject"  (basic java.lang.reflect stuff)
             //
             //System.out.println("c.getName:():" + c.getName());
        
             ctor = c.getDeclaredConstructor(JsonObject.class);
         }
         catch (Exception e)
         {
             if (c.getEnclosingClass() != null)
             {
                 int modifiers = c.getModifiers();
        
                 if ((! Modifier.isStatic(modifiers)) ||  (! Modifier.isPublic(modifiers)))
        
                     throw new JsonException(
                         "Unable to retrieve POJO Constructor for class: " +
                         "[" + c.getName() + "]\n" +
                         "Your class appears to be a Nested-Class, however it has not been " +
                         "declared public and static.  There is no way to retrieve a " +
                         "1-Argument JsonObject Constructor for Nested-Type's unless the " +
                         "type has been declared BOTH static AND public.\n" +
                         "See Exception.getCause() for details.",
                         e
                     );
             }
        
             else throw new JsonException(
                 "Unable to retrieve POJO Constructor for class: [" + c.getName() + "]\n" +
                 "Do you have a one-argument, public, constructor for this class?\n" +
                 "Does it accept a JsonObject in its parameter list?\n" +
                 "See Exception.getCause() for details.",
                 e
             );
         }
        
         // If the user has requested a class that doesn't have that kind of constructor, then
         // there is no way to build the object.  Throw an exception.
        
         if (ctor == null) throw new JsonException(
             "The class which was passed to parameter 'c' [" + c.getName() + "] does not " +
             "appear to have a constructor with precisely one parameter of type JsonObject."
         );
        
         // Call that constructor using the parameter 'jo', and return that instance / object
         try
             { return ctor.newInstance(jo); }
        
         // NOTE: There are *MANY* possible Exception's that may be thrown by reflective
         //       operations like those above.  Furthermore, they are *ALL* checked exceptions.
         //       The code below wraps those exceptions into an UN-CHECKED / RuntimeException
         //       (JsonException)
        
         catch (Exception e)
         {
             throw new JsonException(
                 "Unable to instantiate class: [" + c.getName() + "] using provided " +
                     "Java-Object\n" +
                 "See Exception.getCause() for details.",
                 e
             );
         }
        
      • getString

        🡅  🡇     🗕  🗗  🗖
        public static java.lang.String getString​(JsonArray ja,
                                                 int index,
                                                 boolean throwOnNull)
        Retrieve a JsonArray element, and transform it to a java.lang.String.
        Parameters:
        ja - Any instance of JsonArray
        index - A valid index into array parameter 'ja'. In Json (and unlike Java), array element types are not actually checked for consistency - meaning an array may hold many different types! This array-index must contain a JsonString
        throwOnNull - When TRUE is passed to this parameter, if the JsonArray element located at 'index' contains Json-Null, then this method will throw a JsonNullArrException. When this parameter is FALSE, if the specified array element contains Json-Null, then Java-Null is returned.
        Returns:
        An instance of Java-Type java.lang.String, if the 'ja' array element located at 'index' uses the appropriate Json-Type - JsonString.

        If the specified array element contains Json-Null, and 'throwOnNull' has been passed FALSE, then Java-Null is returned. If the element is null, and 'throwOnNull' is TRUE, then a JsonNullArrException throws.
        Throws:
        java.lang.IndexOutOfBoundsException - If 'index' is out of the bounds of 'ja'
        JsonTypeArrException - If the array-element (specified by 'index') does not actually contain a JsonString (but rather, some other non-null Json-Type), then this exception throws.
        JsonNullArrException - If the JsonArray element specified by 'index' contains a Json-Null, and TRUE has been passed to 'throwOnNull'
        See Also:
        JsonValue.getValueType(), JsonValue.ValueType.STRING
        Code:
        Exact Method Body:
         // This will throw an IndexOutOfBoundsException if the index is out of bounds.
         JsonValue jv = ja.get(index);
        
         switch (jv.getValueType())
         {
             case NULL:
        
                 // This is simple-stuff (not rocket-science).  "Type Mapping" Code has to worry
                 // about what the meaning of "null" should be.
        
                 if (throwOnNull) throw new JsonNullArrException(ja, index, STRING, String.class);
                 else return null;
        
             case STRING: return ((JsonString) jv).getString();
        
             // The JsonValue at the specified array-index does not contain a JsonString.
             default: throw new JsonTypeArrException(ja, index, STRING, jv, String.class);
         }
        
      • getString

        🡅     🗕  🗗  🗖
        public static java.lang.String getString​(JsonObject jo,
                                                 java.lang.String propertyName,
                                                 boolean isOptional,
                                                 boolean throwOnNull)
        Extract a JsonObject property, and transform it to a java.lang.String.
        Parameters:
        jo - Any instance of JsonObject.
        propertyName - The name of the JSON property that should be contained within 'jo'. This property will be retrieved and subsequently transformed / converted to Java-Type java.lang.String.
        isOptional - When TRUE is passed, if 'propertyName' is not actually listed in 'jo' this method shall return Java-Null gracefully. When FALSE is passed, if 'jo' does not have the specified property, a JsonPropMissingException will throw.

        If 'jo' actually has a property named 'propertyName', then the value passed to this parameter is fully irrelevant.
        throwOnNull - When TRUE is passed to this parameter, if the JsonObject property named 'propertyName' evaluates to Json-Null, then this method will throw a JsonNullObjException. When this parameter is FALSE, if the specified property contains Json-Null, then Java-Null is returned.
        Returns:
        An instance of Java-Type java.lang.String', if the 'propertyName' is available inside 'jo', and that property uses the appropriate Json-Type - JsonString.

        If the specified property contains Json-Null, and 'throwOnNull' has been passed FALSE, then Java-Null is returned. If the property is null, and 'throwOnNull' is TRUE, then a JsonNullObjException throws.

        If the specified property is simply missing, Java-Null is returned, unless 'isOptional' has been passed FALSE - in which case a JsonPropMissingException shall be thrown.
        Throws:
        JsonPropMissingException - This exception shall throw if the specified property is missing from the 'JsonObject' (parameter 'jo'). This exception throw can be avoided if 'TRUE' is passed to parameter 'isOptional'.
        JsonTypeObjException - If the property (specified by 'propertyName') is extracted, but that property does not actually contain a JsonString (but rather, some other non-null Json-Type), then this exception throws.
        JsonNullObjException - If the JsonObject property specified by 'propertyName' contains a Json-Null, and TRUE has been passed to 'throwOnNull'
        See Also:
        JsonValue.getValueType(), JsonValue.ValueType.STRING
        Code:
        Exact Method Body:
         if (! jo.containsKey(propertyName))
         {
             if (isOptional) return null;
        
             throw new JsonPropMissingException(jo, propertyName, STRING, String.class);
         }
        
         JsonValue jv = jo.get(propertyName);
        
         switch (jv.getValueType())
         {
             case NULL:
        
                 // This is simple-stuff (not rocket-science).  "Type Mapping" Code has to worry
                 // about what the meaning of "null" should be.
        
                 if (throwOnNull) throw new JsonNullObjException
                     (jo, propertyName, STRING, String.class);
        
                 else return null;
        
             case STRING: return ((JsonString) jv).getString();
        
             // The JsonObject propertydoes not contain a JsonString.
             default: throw new JsonTypeObjException(jo, propertyName, STRING, jv, String.class);
         }