Class JSONParser
- All Implemented Interfaces:
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 -
Method Summary
Modifier and TypeMethodDescriptionvoidbooleanToken(boolean tok) Submits a boolean token from the JSON datavoidIndicates that the parser ran into an ending bracket event ]voidIndicates that the parser ran into an ending bracket event }booleanisAlive()This method indicates to the Parser if this Callback is still alivestatic booleanChecks the default setting for#isIncludeNullsInstance().booleanChecks whether this parser will include null values in parsed content.booleanisStrict()Checks if this JSON parser is in strict mode.static booleanGlobal default setting for#isUseBooleanInstance().booleanIndicates that the parser will generate Boolean objects and not just Strings for boolean valuesstatic booleanChecks whether JSONParser instances will use longs to represent numeric values by default.booleanChecks to see if this parser generates long objects and not just doubles for numeric values.voidThis method is called when a string key/value pair is detected within the json it is essentially redundant when following string/numeric token.voidlongToken(long tok) Submits a numeric token from the JSON datastatic StringStatic method to convert the givenjava.util.Mapto a valid JSON representation.voidnumericToken(double tok) Submits a numeric token from the JSON dataParses the given input stream into this object and returns the parse treestatic voidparse(Reader i, JSONParseCallback callback) 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 voidsetIncludeNulls(boolean aIncludeNullsDefault) Sets the global default settings for#isIncludeNullsInstance().voidsetIncludeNullsInstance(boolean include) Sets whether to include null values in parsed content.voidsetStrict(boolean strict) Enables or disables strict mode.static voidsetUseBoolean(boolean aUseBooleanDefault) Sets the global default value for#isUseBooleanInstance()voidsetUseBooleanInstance(boolean useBoolean) Indicates that the parser will generate Boolean objects and not just Strings for boolean valuesstatic voidsetUseLongs(boolean aUseLongsDefault) Indicates that the parser will generate long objects and not just doubles for numeric values.voidsetUseLongsInstance(boolean longs) Sets the current JSONParser instance to use longs instead of doubles for numeric values.voidstartArray(String arrayName) Indicates that the parser ran into an opening bracket event [voidstartBlock(String blockName) Indicates that the parser ran into an opening bracket event {voidstringToken(String tok) Submits a token from the JSON data as a java string, this token is always a string value
-
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
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
Static method to convert the given
java.util.Mapto a valid JSON representation. The values allowed types are:java.lang.Number,java.lang.String,java.lang.Boolean,java.util.List,java.util.Mapor 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
Parses the given input stream into this object and returns the parse tree.
The
JSONParserreturns aMapwhich is great if the root object is aMapbut 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
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
Indicates that the parser ran into an opening bracket event {- Specified by:
startBlockin interfaceJSONParseCallback
-
endBlock
Indicates that the parser ran into an ending bracket event }- Specified by:
endBlockin interfaceJSONParseCallback
-
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. -
\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
strict: True to enable strict mode, false to disable it.
See also
- #isStrict()
-
-
startArray
Indicates that the parser ran into an opening bracket event [- Specified by:
startArrayin interfaceJSONParseCallback
-
endArray
Indicates that the parser ran into an ending bracket event ]- Specified by:
endArrayin interfaceJSONParseCallback
-
stringToken
Submits a token from the JSON data as a java string, this token is always a string value- Specified by:
stringTokenin interfaceJSONParseCallback
-
numericToken
public void numericToken(double tok) Submits a numeric token from the JSON data
Parameters
tok: the token value
- Specified by:
numericTokenin interfaceJSONParseCallback
-
longToken
public void longToken(long tok) Submits a numeric token from the JSON data- Specified by:
longTokenin interfaceJSONParseCallback
-
booleanToken
public void booleanToken(boolean tok) Submits a boolean token from the JSON data
Parameters
tok: the token value
- Specified by:
booleanTokenin interfaceJSONParseCallback
-
keyValue
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:
keyValuein interfaceJSONParseCallback
-
-
isAlive
public boolean isAlive()This method indicates to the Parser if this Callback is still alive
Returns
- Specified by:
isAlivein interfaceJSONParseCallback- Returns:
- true if the Callback is still interested to get the JSON parse events from the JSONParser
-