public class JSONParser
- Object
- JSONParser
ImplementsJSONParseCallback
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<Map<String, Object>> content = (java.util.List<Map<String, Object>>)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<Map<String, Object>> 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<Map<String, Object>>)response.get("listings");
} catch(Exception err) {
Log.e(err);
return null;
}
}
Nested types
class JSONParser.RawJson | Wrapper that lets a caller embed a pre-built JSON fragment into a Map/List tree being serialized by toJson(Object). |
Constructors
public JSONParser() |
Methods
public static boolean isUseLongs() | Deprecated Checks whether JSONParser instances will use longs to represent numeric values by default. |
public static void setUseLongs(boolean aUseLongsDefault) | Deprecated Indicates that the parser will generate long objects and not just doubles for numeric values. |
public static boolean isIncludeNulls() | Deprecated Checks the default setting for #isIncludeNullsInstance(). |
public static void setIncludeNulls(boolean aIncludeNullsDefault) | Deprecated Sets the global default settings for #isIncludeNullsInstance(). |
public static boolean isUseBoolean() | Deprecated Global default setting for #isUseBooleanInstance(). |
public static void setUseBoolean(boolean aUseBooleanDefault) | Deprecated Sets the global default value for #isUseBooleanInstance() |
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. |
public static String mapToJson(Map<String, ?> map) | Static method to convert the given java.util.Map to a valid JSON representation. |
public static Map<String, Object> parseJSON(byte[] bytes)
throws IOException | Convenience: parse a JSON object from a UTF-8 byte array. |
public static Map<String, Object> parseJSON(String json)
throws IOException | Convenience: parse a JSON object from an in-memory String. |
public static JSONParser.RawJson rawJson(String json) | Creates a RawJson marker. |
public static String toJson(Object value) | Serializes a Map/List/String/Number/Boolean/null / RawJson tree to JSON. |
public static Map<String, Object> asMap(Object o) | Cast helper for the Hashtable/Vector-style return values from parseJSON(java.io.Reader). |
public static List<Object> asList(Object o) | Cast helper for list-typed values pulled out of a parsed JSON tree. |
public static String getString(Map m, String key) | Retrieves a String field from a parsed JSON object. |
public static int getInt(Map m, String key, int defaultValue) | Retrieves an int field from a parsed JSON object, with a fallback when the key is missing, the map is null, or the value cannot be parsed as an integer. |
public static double getDouble(Map m, String key, double defaultValue) | Retrieves a double field from a parsed JSON object, with a fallback when the key is missing, the map is null, or the value cannot be parsed as a number. |
public boolean isUseLongsInstance() | Checks to see if this parser generates long objects and not just doubles for numeric values. |
public void setUseLongsInstance(boolean longs) | Sets the current JSONParser instance to use longs instead of doubles for numeric values. |
public boolean isIncludeNullsInstance() | Checks whether this parser will include null values in parsed content. |
public void setIncludeNullsInstance(boolean include) | Sets whether to include null values in parsed content. |
public boolean isUseBooleanInstance() | Indicates that the parser will generate Boolean objects and not just Strings for boolean values |
public void setUseBooleanInstance(boolean useBoolean) | Indicates that the parser will generate Boolean objects and not just Strings for boolean values |
public Map<String, Object> parseJSON(Reader i)
throws IOException | Parses the given input stream into this object and returns the parse tree. |
public Hashtable<String, Object> parse(Reader i)
throws IOException | Deprecated Parses the given input stream into this object and returns the parse tree |
public void startBlock(String blockName) | Indicates that the parser ran into an opening bracket event { |
public void endBlock(String blockName) | Indicates that the parser ran into an ending bracket event } |
public boolean isStrict() | Checks if this JSON parser is in strict mode. |
public void setStrict(boolean strict) | Enables or disables strict mode. |
public void startArray(String arrayName) | Indicates that the parser ran into an opening bracket event [ |
public void endArray(String arrayName) | Indicates that the parser ran into an ending bracket event ] |
public void stringToken(String tok) | Submits a token from the JSON data as a java string, this token is always a string value |
public void numericToken(double tok) | Submits a numeric token from the JSON data |
public void longToken(long tok) | Submits a numeric token from the JSON data |
public void booleanToken(boolean tok) | Submits a boolean token from the JSON data |
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. |
public boolean isAlive() | This method indicates to the Parser if this Callback is still alive |
Inherited methods
Constructor details
JSONParser
public JSONParser()Method details
isUseLongs
public static boolean isUseLongs()#isUseLongsInstance() to check whether the current JSONParser uses longs.#isUseLongsInstance() to check the status for a particular
JSONParser object.Returns
setUseLongs
public static void setUseLongs(boolean aUseLongsDefault)#setUseLongsInstance(boolean)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
aUseLongsDefaultboolean- the useLongsDefault to set
isIncludeNulls
public static boolean isIncludeNulls()#isIncludeNullsInstance() instead.#isIncludeNullsInstance().Returns
#isIncludeNullsInstance().setIncludeNulls
public static void setIncludeNulls(boolean aIncludeNullsDefault)#setIncludeNullsInstance(boolean) instead.#isIncludeNullsInstance().Parameters
aIncludeNullsDefaultboolean- the includeNullsDefault to set
isUseBoolean
public static boolean isUseBoolean()#isUseBooleanInstance() instead.#isUseBooleanInstance().Returns
setUseBoolean
public static void setUseBoolean(boolean aUseBooleanDefault)#setUseBooleanInstance(boolean) instead.#isUseBooleanInstance()Parameters
aUseBooleanDefaultboolean- the useBooleanDefault to set
parse
public static void parse(Reader i, JSONParseCallback callback)
throws IOExceptionParameters
iReader- the reader
callbackJSONParseCallback- a generic callback to receive the parse events
Throws
IOException- if thrown by the stream
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
mapMap<String, ?>- The map to be converted to a JSON string
Returns
parseJSON
public static Map<String, Object> parseJSON(byte[] bytes)
throws IOExceptionparseJSON(Reader) overload is the canonical entry point but
callers that already have bytes in hand don’t need to wire up
a ByteArrayInputStream + InputStreamReader themselves.Throws
parseJSON
public static Map<String, Object> parseJSON(String json)
throws IOExceptionThrows
rawJson
public static JSONParser.RawJson rawJson(String json)RawJson marker. See the class javadoc for usage.toJson
public static String toJson(Object value)Serializes a Map/List/String/Number/Boolean/null /
RawJson tree to JSON. Differs from mapToJson(Map) in three
ways: it takes any root type (not just Map); it omits
null-valued Map entries (rather than emitting "key":null,
which many REST APIs reject); and it understands the RawJson
sentinel so callers can splice pre-built fragments into the
tree without re-escaping them.
Map keys must be String. Floats and doubles serialize
using Double.toString (no scientific notation for typical
values); integral types (Integer, Long, etc.) serialize as
integers.
asMap
public static Map<String, Object> asMap(Object o)Hashtable/Vector-style return values
from parseJSON(java.io.Reader). Returns null when the
input is null; callers wishing to walk a JSON object tree
without sprinkling (Map) casts everywhere can pass each
nested value through this.asList
public static List<Object> asList(Object o)asMap.getString
public static String getString(Map m, String key)null if the key is missing or the map is null; calls
toString() on non-String values for resilience.getInt
public static int getInt(Map m, String key, int defaultValue)null, or the
value cannot be parsed as an integer.getDouble
public static double getDouble(Map m, String key, double defaultValue)null, or the
value cannot be parsed as a number.isUseLongsInstance
public boolean isUseLongsInstance()setUseLongsInstance
public void setUseLongsInstance(boolean longs)#setUseLongs(boolean)
so that it doesn’t disrupt libraries that may depend on JSONParser.Parameters
longsboolean- True to use
isIncludeNullsInstance
public boolean isIncludeNullsInstance()Returns
setIncludeNullsInstance
public void setIncludeNullsInstance(boolean include)Parameters
includeboolean- True to include null values in parsed content.
isUseBooleanInstance
public boolean isUseBooleanInstance()Returns
setUseBooleanInstance
public void setUseBooleanInstance(boolean useBoolean)Parameters
useBooleanboolean- True to generate Boolean objects and not just Strings for boolean values.
parseJSON
public Map<String, Object> parseJSON(Reader i)
throws IOExceptionParses 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<Map<String, Object>> content = (java.util.List<Map<String, Object>>)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
iReader- the reader
Returns
Throws
IOException- if thrown by the stream
parse
public Hashtable<String, Object> parse(Reader i)
throws IOExceptionParameters
iReader- the reader
Returns
Throws
IOException- if thrown by the stream
startBlock
public void startBlock(String blockName)endBlock
public void endBlock(String blockName)isStrict
public boolean isStrict()Returns
See also
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.\xABHex escapes are converted to JSON unicode escapes.\012Octal escapes are converted to JSON unicode escapes.0xABHex integer literals are converted to JSON decimal numbers.012Octal integer literals are converted to JSON decimal numbers.+.5Decimal numbers are coerced to JSON’s stricter format.[0,,2]Elisions in arrays are filled withnull.[1,2,3,]Trailing commas are removed.{foo:"bar"}Unquoted property names are quoted.//commentsJS style line and block comments are removed.(...)Grouping parentheses are removed.
Parameters
strictboolean- True to enable strict mode, false to disable it.
See also
startArray
public void startArray(String arrayName)endArray
public void endArray(String arrayName)stringToken
public void stringToken(String tok)numericToken
public void numericToken(double tok)Parameters
tokdouble- the token value
longToken
public void longToken(long tok)booleanToken
public void booleanToken(boolean tok)Parameters
tokboolean- the token value
keyValue
public void keyValue(String key, String value)Parameters
keyString- the key
valueString- a string value
isAlive
public boolean isAlive()