Example 1 - Convenient way: Use JSONValue
System.out.println("=======decode=======");
String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]";
Object obj=JSONValue.parse(s);
JSONArray array=(JSONArray)obj;
System.out.println("======the 2nd element of array======");
System.out.println(array.get(1));
System.out.println();
JSONObject obj2=(JSONObject)array.get(1);
System.out.println("======field \"1\"==========");
System.out.println(obj2.get("1"));
s="{}";
obj=JSONValue.parse(s);
System.out.println(obj);
s="[5,]";
obj=JSONValue.parse(s);
System.out.println(obj);
s="[5,,2]";
obj=JSONValue.parse(s);
System.out.println(obj);
JSONObject is a java.util.Map and JSONArray is a java.util.List, so you can access them with standard operations of Map or List. Please referMapping Between JSON and Java Entities for more information on entity mapping while parsing.
Example 2 - Faster way: Reuse instance of JSONParser
JSONParser parser=new JSONParser();
System.out.println("=======decode=======");
String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]";
Object obj=parser.parse(s);
JSONArray array=(JSONArray)obj;
System.out.println("======the 2nd element of array======");
System.out.println(array.get(1));
System.out.println();
JSONObject obj2=(JSONObject)array.get(1);
System.out.println("======field \"1\"==========");
System.out.println(obj2.get("1"));
s="{}";
obj=parser.parse(s);
System.out.println(obj);
s="[5,]";
obj=parser.parse(s);
System.out.println(obj);
s="[5,,2]";
obj=parser.parse(s);
System.out.println(obj);
JSONObject is a java.util.Map and JSONArray is a java.util.List, so you can access them with standard operations of Map or List. Please referMapping Between JSON and Java Entities for more information on entity mapping while parsing.
Example 3 - Exception handling
String jsonText = "[[null, 123.45, \"a\\tb c\"]}, true";
JSONParser parser = new JSONParser();
try{
parser.parse(jsonText);
}
catch(ParseException pe){
System.out.println("position: " + pe.getPosition());
System.out.println(pe);
}
Result:
position: 25
Unexpected token RIGHT BRACE(}) at position 25.
Please refer ParseException.java for more information.
Example 4 - Container factory
You can use ContainerFactory to create containers for parsed JSON objects and JSON arrays:
String jsonText = "{\"first\": 123, \"second\": [4, 5, 6], \"third\": 789}";
JSONParser parser = new JSONParser();
ContainerFactory containerFactory = new ContainerFactory(){
public List creatArrayContainer() {
return new LinkedList();
}
public Map createObjectContainer() {
return new LinkedHashMap();
}
};
try{
Map json = (Map)parser.parse(jsonText, containerFactory);
Iterator iter = json.entrySet().iterator();
System.out.println("==iterate result==");
while(iter.hasNext()){
Map.Entry entry = (Map.Entry)iter.next();
System.out.println(entry.getKey() + "=>" + entry.getValue());
}
System.out.println("==toJSONString()==");
System.out.println(JSONValue.toJSONString(json));
}
catch(ParseException pe){
System.out.println(pe);
}
Result:
==iterate result==
first=>123
second=>[4, 5, 6]
third=>789
==toJSONString()==
{"first":123,"second":[4,5,6],"third":789}
If you don't specify a container factory, org.json.simple.JSONObject is used for a Map and org.json.simple.JSONArray is used for a List. Please refer Mapping Between JSON and Java Entities for more information on entity mapping while parsing.
Example 5 - Stoppable SAX-like content handler
JSON.simple introduces a simplified and stoppable SAX-like content handler to process JSON text stream. The user can pause at any point of the logical input stream, processing other logic, then resume parsing if needed, or abort parsing if he gets the desired result, without having to wait for the whole input stream to finish. Then we have a very fast parser without sacrificing the flexibility. Here's an example of finding values of any object entry that matches a desired key:
KeyFinder.java:
class KeyFinder implements ContentHandler{
private Object value;
private boolean found = false;
private boolean end = false;
private String key;
private String matchKey;
public void setMatchKey(String matchKey){
this.matchKey = matchKey;
}
public Object getValue(){
return value;
}
public boolean isEnd(){
return end;
}
public void setFound(boolean found){
this.found = found;
}
public boolean isFound(){
return found;
}
public void startJSON() throws ParseException, IOException {
found = false;
end = false;
}
public void endJSON() throws ParseException, IOException {
end = true;
}
public boolean primitive(Object value) throws ParseException, IOException {
if(key != null){
if(key.equals(matchKey)){
found = true;
this.value = value;
key = null;
return false;
}
}
return true;
}
public boolean startArray() throws ParseException, IOException {
return true;
}
public boolean startObject() throws ParseException, IOException {
return true;
}
public boolean startObjectEntry(String key) throws ParseException, IOException {
this.key = key;
return true;
}
public boolean endArray() throws ParseException, IOException {
return false;
}
public boolean endObject() throws ParseException, IOException {
return true;
}
public boolean endObjectEntry() throws ParseException, IOException {
return true;
}
}
Main logic:
String jsonText = "{\"first\": 123, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5, 6, {\"id\": 123}], \"third\": 789, \"id\": null}";
JSONParser parser = new JSONParser();
KeyFinder finder = new KeyFinder();
finder.setMatchKey("id");
try{
while(!finder.isEnd()){
parser.parse(jsonText, finder, true);
if(finder.isFound()){
finder.setFound(false);
System.out.println("found id:");
System.out.println(finder.getValue());
}
}
}
catch(ParseException pe){
pe.printStackTrace();
}
Result:
found id:
id1
found id:
123
found id:
null
Please refer ContentHandler.java for more information.
Example 6 - Build whole object graph on top of SAX-like content handler
Please note that JSON.simple has provided the build in functionality to do the same work. Please refer above examples for more information. Here is just an example to show how to use the SAX-like interface in a slightly more complex scenario.
Transformer.java:
class Transformer implements ContentHandler{
private Stack valueStack;
public Object getResult(){
if(valueStack == null || valueStack.size() == 0)
return null;
return valueStack.peek();
}
public boolean endArray () throws ParseException, IOException {
trackBack();
return true;
}
public void endJSON () throws ParseException, IOException {}
public boolean endObject () throws ParseException, IOException {
trackBack();
return true;
}
public boolean endObjectEntry () throws ParseException, IOException {
Object value = valueStack.pop();
Object key = valueStack.pop();
Map parent = (Map)valueStack.peek();
parent.put(key, value);
return true;
}
private void trackBack(){
if(valueStack.size() > 1){
Object value = valueStack.pop();
Object prev = valueStack.peek();
if(prev instanceof String){
valueStack.push(value);
}
}
}
private void consumeValue(Object value){
if(valueStack.size() == 0)
valueStack.push(value);
else{
Object prev = valueStack.peek();
if(prev instanceof List){
List array = (List)prev;
array.add(value);
}
else{
valueStack.push(value);
}
}
}
public boolean primitive (Object value) throws ParseException, IOException {
consumeValue(value);
return true;
}
public boolean startArray () throws ParseException, IOException {
List array = new JSONArray();
consumeValue(array);
valueStack.push(array);
return true;
}
public void startJSON () throws ParseException, IOException {
valueStack = new Stack();
}
public boolean startObject () throws ParseException, IOException {
Map object = new JSONObject();
consumeValue(object);
valueStack.push(object);
return true;
}
public boolean startObjectEntry (String key) throws ParseException, IOException {
valueStack.push(key);
return true;
}
}
Main logic:
String jsonString = <Input JSON text>;
Object value = null;
JSONParser parser = new JSONParser();
Transformer transformer = new Transformer();
parser.parse(jsonString, transformer);
value = transformer.getResult();
The result is similar to one return from the following code:
String jsonString = <Input JSON text>;
Object value = null;
JSONParser parser = new JSONParser();
value = parser.parse(jsonString);
Notes - Multithreading and extensions
JSONParser is NOT thread-safe. And please note that JSON string such as [5,,,2] is accepted by the parser and is treated as [5,2]. This doesn't violate the JSON specification, and it increases the error toleration of the input data. Some JSON grammar checker may need a 'strict' mode. Considering adding this feature.
Since it's a bit controversial on the extension of the parser (see comments of this wiki page), I'd like to make some clarifications on this topic here.
Some users may concern about exchanging important data, say medical information or financial data, between applications. I think you need to make sure the following things in such scenarios:
- You need to make sure you are using a reliable and full compliant encoder on the side of the source;
- Or if you also accept data from a non-trusted source, even a 'strict' decoder is inadequate. You may need extra validation rules to verify the source. For example, a user may send totally compliant [5,2] even though you expect [5,0,2].
In both cases, a liberal parser will do nothing harmful to your application.
The reason of accepting something like [5,,2] is that:
- A careless user or an encoder may repeat a comma (such as by pressing the key too long :-), which is harmless;
- The comma is actually redundant syntactically, if two adjacent entities are recognized.
I know some users may be FUD in front of a liberal parser, but as I mentioned above, it's harmless and is allowed in RFC4627 (actually the author of RFC4627 adopts this feature in the reference implementation).
Please feel free to leave a comment or post in the discussion group if you have further concerns. Thanks.
Actually, why wouldn't such a non-standard feature violate JSON specification? Such a construct does not conform to the JSON syntax, so by definition it seems to explicitly violate it. And the main problem is that accepting such invalid input reduces interoperability -- other parser will not accept such structures, and it may make users less likely to use json.simple, because its behavior differs from standard behavior.
RFC 4627 states:
It does not cause interoperability issues because the encoding is always right, and JSON.simple always accepts inputs that conform to the JSON grammar.
Actually, JSON.org's RI goes further on extension. It accepts single quote strings and hex number: ['total' : 0x20].
Yes, RI is non-compliant as well. It is true that specification allows for extensions; unfortunately there are no commonly defined "common" extensions and thus each parser seems to adopt their own favorite hacks.
But it is bit naive to think that accepting non-valid input would not lead to interoperability problems -- this is EXACTLY how browsers degenerated into accepting all kinds of broken html. So personally I think it is wrong to add short-cuts for what are essentially broken documents (missing values, or extra commas).
But it is your parser of course, and you can add any extensions that you like. :-)
Please read RFC4627 carefully, then you'll find the lines as below:
That is, the encoder should be always right, so the interoperability problem will never happen. The extension of the parser is to increase the robustness of the application. Both the RI and JSON.simple are fully compliant with RFC4627. If you insists that there will be interoperability problems, it's the problem of the specification, not the library. But the fact is, it will never happen.
I agree with tsaloranta.
Accepting non-compliant input creates the risk of letting non-compliant content spread (e.g. contents generated by hand, or by another system that has a flaw). As long as the only "client" to these contents is read by a "tolerant" parser you have no problem.
The day another system, using a more strict parser, comes into play, you have your interoperability problem, and it might be too late to come back.
arnauldvm, tsaloranta: Please take the time to review Postel's Law: "Be conservative in what you do; be liberal in what you accept from others."
http://en.wikipedia.org/wiki/Postel%27s_law
The responsibility for enforcing valid JSON lies with the encoder, not the decoder. The decoder's sole responsibility is to parse JSON. By gracefully accepting invalid input, the decoder becomes more robust and usable.
"Be conservative in what you do; be liberal in what you accept from others."
The complication lies in that "accepting" means making assumptions about the intention of the author. Does "5,,,2" mean "5,2", or "5,null,null,2", "5,0,0,2", or something else?
I suspect that if I were parsing, say, important medical data, I would need a strict mode, that would fail in this case, or at least warn somehow.
Hi keithdwinkler, if you are exchanging important data, say medical information or financial data, between applications, I think you need to make sure the following things in such scenarios:
In both cases, a liberal parser will do nothing harmful to your application.
The reason of accepting something like [5,,2] is that:
I know some users may be FUD in front of a liberal parser, but as I mentioned above, it's harmless and is allowed in RFC4627 (actually the author of RFC4627 adopts this feature in the reference implementation).
Please feel free to leave a comment or post in the discussion group if you have further concerns. Thanks.
Any particular reason why JSONValue.parse(s) returns an Object and not a more proper JSONObject?
Because we also have a JSONArray and other primitives.
I have a simple, irrefutable need for a completely strict parser: I have a piece of code that produces JSON, so I need a strict parser to validate it during unit tests. I tried to use JSONObject(), but of course JSONObject accepts invalid JSON, so my tests pass even though my program is incorrect.
Can someone recommend an easy-to-use, open-source Java library that throws an exception when it encounters invalid JSON?
To unit test the JSON output, compare it to a static string that is the expected output. If you attempt to do anything else you are doing one or more of:
Either of those is bad. The best solution is to compare the output to the expected value, which would be a string, rather than parsing it.
please PLEASE add strict mode. The reason being is that I want to know if system A is sending input like 1,,,,5 early on so that if we have system A start sending to other systems(not just json-simple), we won't know. it is easier to start strict and move to more flexible than it is to go from flexible to strict....heck try adding checkstyle to a 3.0 project vs. adding it to a 0.1 release project...big difference on making things stricter...it's harder to go one way then the other.
Maybe this isnt exactly the place to be asking questions, but im new to java and im having an issue with the container class example I literally copied and pasted the code into my class to attempt to decode the following which was passed back from the server side {"uid":2,"name":"john"}{"uid":3,"name":"mary"} so essentially (int,string) I believe the error is from the line return new LinkedHashMap?(); and the error is Unexpected token LEFT BRACE({) at position 23.
Any help would be appreciated Regards
@finbar, your JSON represents two objects. The code works with just one, ie {"uid":2,"name":"john"}. The error message is the parser complaining about the left brace at the start of the second object (ie 23 characters in).
Since the server sent separate JSON strings (it didn't return an array?), then you could call the example piece of code once for each individual string.
How can we disable the display of JSON value in "View Source" of a browser?
I noticed a critical error in the JSON Maps mentioned in the below code: Map json = (Map)parser.parse(jsonText, containerFactory);
Object obj=JSONValue.parse(json2.get("items").toString()); JSONArray array=(JSONArray)obj;There one of the key item is an array that has some strings, but it is failing to parse that array list, because it is removing all the quotes """ from the key values, so we cannot process it further as arrays, I think its a major flaw.
I tried to reproduce your major flaw but I'm not sure if you provided all the information needed.
Dear,
I have following json responce. I am not able to iterate through each Map. Please help me
{"status":"OK","result":{"1":{"Id":"3","Conferencce":"test3","Description":"test3","Admin":"919818559890","Moderator":null,"Keywords":"test3","StartDate?":"2011-11-19 12:22:33","EndDate?":"2011-11-19 14:22:33","Type":"both","MaxAtendee?":"0","MinAtendee?":"0","RegAtendee?":"0","DescVoiceVideo?":null,"Rating":null,"Status":"active","ApproveBy?":null,"ApprovedOn?":"2011-11-15 14:22:33","ApprovedReason?":null,"AdminPin?":null,"UserPin?":null,"PricePerMin?":null,"PricePerConf?":null,"ReminderStart?":null,"AdminJoin?":null,"CreatedOn?":"2011-11-17 13:31:27","CreatedBy?":"1"},"2":{"Id":"2","Conferencce":"test2","Description":"test","Admin":"919818559899","Moderator":null,"Keywords":"test2","StartDate?":"2011-11-18 12:22:33","EndDate?":"2011-11-18 14:22:33","Type":"both","MaxAtendee?":"0","MinAtendee?":"0","RegAtendee?":"0","DescVoiceVideo?":null,"Rating":null,"Status":"active","ApproveBy?":null,"ApprovedOn?":"2011-11-15 12:22:33","ApprovedReason?":null,"AdminPin?":null,"UserPin?":null,"PricePerMin?":null,"PricePerConf?":null,"ReminderStart?":null,"AdminJoin?":null,"CreatedOn?":"2011-11-17 13:31:20","CreatedBy?":"1"},"3":{"Id":"1","Conferencce":"test","Description":"tes","Admin":"919818559898","Moderator":null,"Keywords":"test","StartDate?":"2011-11-17 12:22:33","EndDate?":"2011-11-17 14:22:33","Type":"both","MaxAtendee?":"0","MinAtendee?":"0","RegAtendee?":"0","DescVoiceVideo?":null,"Rating":null,"Status":"active","ApproveBy?":"1","ApprovedOn?":"2011-11-15 12:22:33","ApprovedReason?":null,"AdminPin?":null,"UserPin?":null,"PricePerMin?":null,"PricePerConf?":null,"ReminderStart?":null,"AdminJoin?":null,"CreatedOn?":"2011-11-17 13:31:15","CreatedBy?":"1"}}}
How can I marshal this "device" object using ContainerFactory??
{
}I have a input stream (bound to a socket), that continuously gives multiple JSON docs, and I want to parse it one by one. If i use json-simple, it will stop at the beginning of the second JSON doc ('{') with an exception.
How can I parse multiple JSON docs in one stream??
[{"name":"1350458288_11294.jpg","size":775702,"type":"image\/jpeg","url":"http:\/\/localhost\/oto\/files\/1350458288_11294.jpg","thumbnail_url":"http:\/\/localhost\/oto\/thumbnails\/1350458288_11294.jpg","delete_url":"http:\/\/localhost\/oto\/?file=1350458288_11294.jpg","delete_type":"DELETE"}]
whats is Json ?
Hi, i have a question about reading json file. In file I have several lines. Each line with {}. How can i parse some data from each line in a loop? Thanks a lot!!
I just added this class util to my project:
import org.json.simple.JSONObject;
public class JSONObjectUtil {
}In this way, retrieving a value from a JSONObject is pretty simple:
JSONObjectUtil.retrieveJsonPath(json, "glossary/GlossDiv?/GlossList?/GlossEntry?/SortAs?")
A lot of people are asking for recursive iteration. This is my solution.
A class with static print methods for printing and navigating through Map and List objects.
A ContainerFactory? returning the types I want:
And you can call it like this:
Thanks for JSON recursive function. I need to manipulate(add,delete and update) my JSON string and then reform the JSON object
{ }