Class JSONParser

java.lang.Object
com.codename1.io.JSONParser
All Implemented Interfaces:
JSONParseCallback

public class JSONParser extends Object implements JSONParseCallback

Fast and dirty parser for JSON content on the web, it essentially returns a java.util.Map object containing the object fields mapped to their values. If the value is a nested object a nested java.util.Map/java.util.List is returned.

The JSONParser returns a Map which is great if the root object is a Map but in some cases its a list of elements (as is the case above). In this case a special case "root" element is created to contain the actual list of elements. See the sample below for exact usage of this.

The sample below includes JSON from https://anapioficeandfire.com/ generated by the query http://www.anapioficeandfire.com/api/characters?page=5&pageSize=3:

// File: JSONParsingSample.java
Form hi = new Form("JSON Parsing", new BoxLayout(BoxLayout.Y_AXIS));
JSONParser json = new JSONParser();
try(Reader r = new InputStreamReader(Display.getInstance().getResourceAsStream(getClass(), "/anapioficeandfire.json"), "UTF-8")) {
    Map data = json.parseJSON(r);
    java.util.List> content = (java.util.List>)data.get("root");
    for(Map obj : content) {
        String url = (String)obj.get("url");
        String name = (String)obj.get("name");
        java.util.List titles = (java.util.List)obj.get("titles");
        if(name == null || name.length() == 0) {
            java.util.List aliases = (java.util.List)obj.get("aliases");
            if(aliases != null && aliases.size() > 0) {
                name = aliases.get(0);
            }
        }
        MultiButton mb = new MultiButton(name);
        if(titles != null && titles.size() > 0) {
            mb.setTextLine2(titles.get(0));
        }
        mb.addActionListener((e) -> Display.getInstance().execute(url));
        hi.add(mb);
    }
} catch(IOException err) {
    Log.e(err);
}
hi.show();
// File: anapioficeandfire.json
[
  {
    "url": "http://www.anapioficeandfire.com/api/characters/13",
    "name": "Chayle",
    "culture": "",
    "born": "",
    "died": "In 299 AC, at Winterfell",
    "titles": [
      "Septon"
    ],
    "aliases": [],
    "father": "",
    "mother": "",
    "spouse": "",
    "allegiances": [],
    "books": [
      "http://www.anapioficeandfire.com/api/books/1",
      "http://www.anapioficeandfire.com/api/books/2",
      "http://www.anapioficeandfire.com/api/books/3"
    ],
    "povBooks": [],
    "tvSeries": [],
    "playedBy": []
  },
  {
    "url": "http://www.anapioficeandfire.com/api/characters/14",
    "name": "Gillam",
    "culture": "",
    "born": "",
    "died": "",
    "titles": [
      "Brother"
    ],
    "aliases": [],
    "father": "",
    "mother": "",
    "spouse": "",
    "allegiances": [],
    "books": [
      "http://www.anapioficeandfire.com/api/books/5"
    ],
    "povBooks": [],
    "tvSeries": [],
    "playedBy": []
  },
  {
    "url": "http://www.anapioficeandfire.com/api/characters/15",
    "name": "High Septon",
    "culture": "",
    "born": "",
    "died": "",
    "titles": [
      "High Septon",
      "His High Holiness",
      "Father of the Faithful",
      "Voice of the Seven on Earth"
    ],
    "aliases": [
      "The High Sparrow"
    ],
    "father": "",
    "mother": "",
    "spouse": "",
    "allegiances": [],
    "books": [
      "http://www.anapioficeandfire.com/api/books/5",
      "http://www.anapioficeandfire.com/api/books/8"
    ],
    "povBooks": [],
    "tvSeries": [
      "Season 5"
    ],
    "playedBy": [
      "Jonathan Pryce"
    ]
  }
]

The sample code below fetches a page of data from the nestoria housing listing API as a list of Map elements. You can see instructions on how to display the data in the com.codename1.components.InfiniteScrollAdapter class.

int pageNumber = 1;
java.util.List> fetchPropertyData(String text) {
    try {
        ConnectionRequest r = new ConnectionRequest();
        r.setPost(false);
        r.setUrl("http://api.nestoria.co.uk/api");
        r.addArgument("pretty", "0");
        r.addArgument("action", "search_listings");
        r.addArgument("encoding", "json");
        r.addArgument("listing_type", "buy");
        r.addArgument("page", "" + pageNumber);
        pageNumber++;
        r.addArgument("country", "uk");
        r.addArgument("place_name", text);
        NetworkManager.getInstance().addToQueueAndWait(r);
        Map result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
        Map response = (Map)result.get("response");
        return (java.util.List>)response.get("listings");
    } catch(Exception err) {
        Log.e(err);
        return null;
    }
}
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    booleanToken(boolean tok)
    Submits a boolean token from the JSON data
    void
    endArray(String arrayName)
    Indicates that the parser ran into an ending bracket event ]
    void
    endBlock(String blockName)
    Indicates that the parser ran into an ending bracket event }
    boolean
    This method indicates to the Parser if this Callback is still alive
    static boolean
    Checks the default setting for #isIncludeNullsInstance().
    boolean
    Checks whether this parser will include null values in parsed content.
    boolean
    Checks if this JSON parser is in strict mode.
    static boolean
    Global default setting for #isUseBooleanInstance().
    boolean
    Indicates that the parser will generate Boolean objects and not just Strings for boolean values
    static boolean
    Checks whether JSONParser instances will use longs to represent numeric values by default.
    boolean
    Checks to see if this parser generates long objects and not just doubles for numeric values.
    void
    keyValue(String key, String value)
    This method is called when a string key/value pair is detected within the json it is essentially redundant when following string/numeric token.
    void
    longToken(long tok)
    Submits a numeric token from the JSON data
    static String
    Static method to convert the given java.util.Map to a valid JSON representation.
    void
    numericToken(double tok)
    Submits a numeric token from the JSON data
    Parses the given input stream into this object and returns the parse tree
    static void
    Static method! Parses the given input stream and fires the data into the given callback.
    Parses the given input stream into this object and returns the parse tree.
    static void
    setIncludeNulls(boolean aIncludeNullsDefault)
    Sets the global default settings for #isIncludeNullsInstance().
    void
    setIncludeNullsInstance(boolean include)
    Sets whether to include null values in parsed content.
    void
    setStrict(boolean strict)
    Enables or disables strict mode.
    static void
    setUseBoolean(boolean aUseBooleanDefault)
    Sets the global default value for #isUseBooleanInstance()
    void
    setUseBooleanInstance(boolean useBoolean)
    Indicates that the parser will generate Boolean objects and not just Strings for boolean values
    static void
    setUseLongs(boolean aUseLongsDefault)
    Indicates that the parser will generate long objects and not just doubles for numeric values.
    void
    setUseLongsInstance(boolean longs)
    Sets the current JSONParser instance to use longs instead of doubles for numeric values.
    void
    startArray(String arrayName)
    Indicates that the parser ran into an opening bracket event [
    void
    startBlock(String blockName)
    Indicates that the parser ran into an opening bracket event {
    void
    Submits a token from the JSON data as a java string, this token is always a string value

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • JSONParser

      public JSONParser()
  • Method Details

    • isUseLongs

      public static boolean isUseLongs()

      Checks whether JSONParser instances will use longs to represent numeric values by default. This is just a global default setting. You should use #isUseLongsInstance() to check the status for a particular JSONParser object.

      Returns

      the useLongsDefault

      Deprecated

      Use #isUseLongsInstance() to check whether the current JSONParser uses longs.

    • setUseLongs

      public static void setUseLongs(boolean aUseLongsDefault)

      Indicates that the parser will generate long objects and not just doubles for numeric values.

      Warning: This method will affect ALL JSONParser instances in the application. Prefer to use #setUseLongsInstance(boolean) to only affect the behaviour of the particular JSONParser instance.

      Parameters
      • aUseLongsDefault: the useLongsDefault to set
      Deprecated

      Use #setUseLongsInstance(boolean)

    • isIncludeNulls

      public static boolean isIncludeNulls()

      Checks the default setting for #isIncludeNullsInstance().

      Returns

      the includeNullsDefault The global default setting for #isIncludeNullsInstance().

      Deprecated

      Use #isIncludeNullsInstance() instead.

    • setIncludeNulls

      public static void setIncludeNulls(boolean aIncludeNullsDefault)

      Sets the global default settings for #isIncludeNullsInstance().

      Parameters
      • aIncludeNullsDefault: the includeNullsDefault to set
      Deprecated

      Use #setIncludeNullsInstance(boolean) instead.

    • isUseBoolean

      public static boolean isUseBoolean()

      Global default setting for #isUseBooleanInstance().

      Returns

      the useBooleanDefault

      Deprecated

      Use #isUseBooleanInstance() instead.

    • setUseBoolean

      public static void setUseBoolean(boolean aUseBooleanDefault)

      Sets the global default value for #isUseBooleanInstance()

      Parameters
      • aUseBooleanDefault: the useBooleanDefault to set
      Deprecated

      Use #setUseBooleanInstance(boolean) instead.

    • parse

      public static void parse(Reader i, JSONParseCallback callback) throws IOException

      Static method! Parses the given input stream and fires the data into the given callback.

      Parameters
      • i: the reader

      • callback: a generic callback to receive the parse events

      Throws
      • IOException: if thrown by the stream
      Throws:
      IOException
    • mapToJson

      public static String mapToJson(Map<String,?> map)

      Static method to convert the given java.util.Map to a valid JSON representation. The values allowed types are: java.lang.Number, java.lang.String, java.lang.Boolean, java.util.List, java.util.Map or null.

      Limited whitespace is inserted be make the resulting JSON string more readable.

      Simple example of usage:

      `Map person = new LinkedHashMap<>();
      person.put("firstName", "Paco");
      person.put("lastName", "Bellz");
      person.put("isAlive", true);
      person.put("age", 35);
      person.put("weight (kg)", 70.7);
      
      Log.p("--- mapToJson() test");
      Log.p("\n" + mapToJson(person));`
      

      The output will be:

      `{
       "firstName": "Paco",
       "lastName": "Bellz",
       "isAlive": true,
       "age": 35,
       "weight (kg)": 70.7`
      }
      

      More complex example of usage:

      `Map phoneNumber1 = new LinkedHashMap<>();
      phoneNumber1.put("home", "212 555-1234");
      Map phoneNumber2 = new LinkedHashMap<>();
      phoneNumber2.put("office", "646 555-4567");
      Map phoneNumber3 = new LinkedHashMap<>();
      phoneNumber3.put("mobile", "123 456-7890");
      Map phoneNumber4 = new LinkedHashMap<>();
      phoneNumber4.put("mobile", "06124578965");
      ArrayList phoneNumbers = new ArrayList();
      ArrayList phoneNumbers2 = new ArrayList();
      phoneNumbers.add(phoneNumber1);
      phoneNumbers.add(phoneNumber2);
      phoneNumbers.add(phoneNumber3);
      phoneNumbers2.add(phoneNumber4);
      Map address1 = new LinkedHashMap<>();
      address1.put("streetAddress", "53, London Street");
      address1.put("city", "Paris");
      address1.put("state", "FR");
      address1.put("postalCode", "54856");
      Map address2 = new LinkedHashMap<>();
      address2.put("streetAddress", "21 2nd Street");
      address2.put("city", "New York");
      address2.put("state", "NY");
      address2.put("postalCode", "10021-3100");
      Map secondPerson = new LinkedHashMap<>();
      secondPerson.put("firstName", "Gioia");
      secondPerson.put("lastName", "Mia");
      secondPerson.put("isAlive", true);
      secondPerson.put("age", 34);
      secondPerson.put("weight (kg)", 60.2);
      secondPerson.put("address", address2);
      address2.put("phoneNumbers", phoneNumbers2);
      Map firstPerson = new LinkedHashMap<>();
      firstPerson.put("firstName", "Paco");
      firstPerson.put("lastName", "Bellz");
      firstPerson.put("isAlive", true);
      firstPerson.put("age", 35);
      firstPerson.put("weight (kg)", 70.7);
      firstPerson.put("address", address1);
      firstPerson.put("partner", secondPerson);
      firstPerson.put("children", new ArrayList());
      firstPerson.put("extraInfo", null);
      firstPerson.put("phoneNumbers", phoneNumbers);
      List friends = new ArrayList();
      friends.add("Paul");
      friends.add("Karl");
      friends.add("Mary");
      firstPerson.put("onVacation", false);
      firstPerson.put("friends", friends);
      
      Log.p("--- mapToJson() test");
      Log.p("\n" + mapToJson(firstPerson));`
      

      The output will be:

      `{
       "firstName": "Paco",
       "lastName": "Bellz",
       "isAlive": true,
       "age": 35,
       "weight (kg)": 70.7,
       "address": {
         "streetAddress": "53, London Street",
         "city": "Paris",
         "state": "FR",
         "postalCode": "54856"`,
       "partner": {
         "firstName": "Gioia",
         "lastName": "Mia",
         "isAlive": true,
         "age": 34,
         "weight (kg)": 60.2,
         "address": {
           "streetAddress": "21 2nd Street",
           "city": "New York",
           "state": "NY",
           "postalCode": "10021-3100",
           "phoneNumbers": [{"mobile": "06124578965"}]
         }
       },
       "children": [],
       "extraInfo": null,
       "phoneNumbers": [
         {"home": "212 555-1234"},
         {"office": "646 555-4567"},
         {"mobile": "123 456-7890"}
       ],
       "onVacation": false,
       "friends": [
         "Paul",
         "Karl",
         "Mary"
       ]
      }
      }
      
      Parameters
      • map: The map to be converted to a JSON string
      Returns

      The JSON string

    • isUseLongsInstance

      public boolean isUseLongsInstance()
      Checks to see if this parser generates long objects and not just doubles for numeric values.
    • setUseLongsInstance

      public void setUseLongsInstance(boolean longs)

      Sets the current JSONParser instance to use longs instead of doubles for numeric values. Prefer this to the static #setUseLongs(boolean) so that it doesn't disrupt libraries that may depend on JSONParser.

      Parameters
      • longs: True to use
      Since

      7.0

    • isIncludeNullsInstance

      public boolean isIncludeNullsInstance()

      Checks whether this parser will include null values in parsed content.

      Returns

      True if null values are included in parsed content.

      Since

      7.0

    • setIncludeNullsInstance

      public void setIncludeNullsInstance(boolean include)

      Sets whether to include null values in parsed content.

      Parameters
      • include: True to include null values in parsed content.
      Since

      7.0

    • isUseBooleanInstance

      public boolean isUseBooleanInstance()

      Indicates that the parser will generate Boolean objects and not just Strings for boolean values

      Returns

      True if the parser will generate Boolean objects and not just Strings for boolean values.

      Since

      7.0

    • setUseBooleanInstance

      public void setUseBooleanInstance(boolean useBoolean)

      Indicates that the parser will generate Boolean objects and not just Strings for boolean values

      Parameters
      • useBoolean: True to generate Boolean objects and not just Strings for boolean values.
      Since

      7.0

    • parseJSON

      public Map<String,Object> parseJSON(Reader i) throws IOException

      Parses the given input stream into this object and returns the parse tree.

      The JSONParser returns a Map which is great if the root object is a Map but in some cases its a list of elements (as is the case above). In this case a special case "root" element is created to contain the actual list of elements. See the sample below for exact usage of this.

      The sample below includes JSON from https://anapioficeandfire.com/ generated by the query http://www.anapioficeandfire.com/api/characters?page=5&pageSize=3:

      // File: JSONParsingSample.java
      Form hi = new Form("JSON Parsing", new BoxLayout(BoxLayout.Y_AXIS));
      JSONParser json = new JSONParser();
      try(Reader r = new InputStreamReader(Display.getInstance().getResourceAsStream(getClass(), "/anapioficeandfire.json"), "UTF-8")) {
          Map data = json.parseJSON(r);
          java.util.List> content = (java.util.List>)data.get("root");
          for(Map obj : content) {
              String url = (String)obj.get("url");
              String name = (String)obj.get("name");
              java.util.List titles = (java.util.List)obj.get("titles");
              if(name == null || name.length() == 0) {
                  java.util.List aliases = (java.util.List)obj.get("aliases");
                  if(aliases != null && aliases.size() > 0) {
                      name = aliases.get(0);
                  }
              }
              MultiButton mb = new MultiButton(name);
              if(titles != null && titles.size() > 0) {
                  mb.setTextLine2(titles.get(0));
              }
              mb.addActionListener((e) -> Display.getInstance().execute(url));
              hi.add(mb);
          }
      } catch(IOException err) {
          Log.e(err);
      }
      hi.show();
      
      // File: anapioficeandfire.json
      [
        {
          "url": "http://www.anapioficeandfire.com/api/characters/13",
          "name": "Chayle",
          "culture": "",
          "born": "",
          "died": "In 299 AC, at Winterfell",
          "titles": [
            "Septon"
          ],
          "aliases": [],
          "father": "",
          "mother": "",
          "spouse": "",
          "allegiances": [],
          "books": [
            "http://www.anapioficeandfire.com/api/books/1",
            "http://www.anapioficeandfire.com/api/books/2",
            "http://www.anapioficeandfire.com/api/books/3"
          ],
          "povBooks": [],
          "tvSeries": [],
          "playedBy": []
        },
        {
          "url": "http://www.anapioficeandfire.com/api/characters/14",
          "name": "Gillam",
          "culture": "",
          "born": "",
          "died": "",
          "titles": [
            "Brother"
          ],
          "aliases": [],
          "father": "",
          "mother": "",
          "spouse": "",
          "allegiances": [],
          "books": [
            "http://www.anapioficeandfire.com/api/books/5"
          ],
          "povBooks": [],
          "tvSeries": [],
          "playedBy": []
        },
        {
          "url": "http://www.anapioficeandfire.com/api/characters/15",
          "name": "High Septon",
          "culture": "",
          "born": "",
          "died": "",
          "titles": [
            "High Septon",
            "His High Holiness",
            "Father of the Faithful",
            "Voice of the Seven on Earth"
          ],
          "aliases": [
            "The High Sparrow"
          ],
          "father": "",
          "mother": "",
          "spouse": "",
          "allegiances": [],
          "books": [
            "http://www.anapioficeandfire.com/api/books/5",
            "http://www.anapioficeandfire.com/api/books/8"
          ],
          "povBooks": [],
          "tvSeries": [
            "Season 5"
          ],
          "playedBy": [
            "Jonathan Pryce"
          ]
        }
      ]
      
      Parameters
      • i: the reader
      Returns

      the parse tree as a hashtable

      Throws
      • IOException: if thrown by the stream
      Throws:
      IOException
    • parse

      public Hashtable<String,Object> parse(Reader i) throws IOException

      Parses the given input stream into this object and returns the parse tree

      Parameters
      • i: the reader
      Returns

      the parse tree as a hashtable

      Throws
      • IOException: if thrown by the stream
      Deprecated

      use the new parseJSON instead

      Throws:
      IOException
    • startBlock

      public void startBlock(String blockName)
      Indicates that the parser ran into an opening bracket event {
      Specified by:
      startBlock in interface JSONParseCallback
    • endBlock

      public void endBlock(String blockName)
      Indicates that the parser ran into an ending bracket event }
      Specified by:
      endBlock in interface JSONParseCallback
    • isStrict

      public boolean isStrict()

      Checks if this JSON parser is in strict mode. When in strict mode, which is the default, only valid JSON will be parsed. If strict mode is disabled, then it will attempt to sanitize the JSON input before parsing. This can be handy if you want to parse structures that are almost JSON. E.g. non-quoted keys, single-quotes on strings, unquoted strings. Etc.

      Returns

      True if strict mode is enabled.

      Since

      7.0

      See also
      • #setStrict(boolean)
    • setStrict

      public void setStrict(boolean strict)

      Enables or disables strict mode. Default is true.

      When strict mode is disabled, the parser will sanitize the JSON input before parsing. The effect is that it will be able to parse input that is json-ish.

      Non-Strict Input The sanitizer takes JSON like content, and interprets it as JS eval would. Specifically, it deals with these non-standard constructs.

      • '...' Single quoted strings are converted to JSON strings.

      • \xAB Hex escapes are converted to JSON unicode escapes.

      • \012 Octal escapes are converted to JSON unicode escapes.

      • 0xAB Hex integer literals are converted to JSON decimal numbers.

      • 012 Octal integer literals are converted to JSON decimal numbers.

      • +.5 Decimal numbers are coerced to JSON's stricter format.

      • [0,,2] Elisions in arrays are filled with null.

      • [1,2,3,] Trailing commas are removed.

      • {foo:"bar"} Unquoted property names are quoted.

      • //comments JS style line and block comments are removed.

      • (...) Grouping parentheses are removed.

      Parameters
      • strict: True to enable strict mode, false to disable it.
      See also
      • #isStrict()
    • startArray

      public void startArray(String arrayName)
      Indicates that the parser ran into an opening bracket event [
      Specified by:
      startArray in interface JSONParseCallback
    • endArray

      public void endArray(String arrayName)
      Indicates that the parser ran into an ending bracket event ]
      Specified by:
      endArray in interface JSONParseCallback
    • stringToken

      public void stringToken(String tok)
      Submits a token from the JSON data as a java string, this token is always a string value
      Specified by:
      stringToken in interface JSONParseCallback
    • numericToken

      public void numericToken(double tok)

      Submits a numeric token from the JSON data

      Parameters
      • tok: the token value
      Specified by:
      numericToken in interface JSONParseCallback
    • longToken

      public void longToken(long tok)
      Submits a numeric token from the JSON data
      Specified by:
      longToken in interface JSONParseCallback
    • booleanToken

      public void booleanToken(boolean tok)

      Submits a boolean token from the JSON data

      Parameters
      • tok: the token value
      Specified by:
      booleanToken in interface JSONParseCallback
    • keyValue

      public void keyValue(String key, String value)

      This method is called when a string key/value pair is detected within the json it is essentially redundant when following string/numeric token.

      Parameters
      • key: the key

      • value: a string value

      Specified by:
      keyValue in interface JSONParseCallback
    • isAlive

      public boolean isAlive()

      This method indicates to the Parser if this Callback is still alive

      Returns
      Specified by:
      isAlive in interface JSONParseCallback
      Returns:
      true if the Callback is still interested to get the JSON parse events from the JSONParser