Processing a string formatted as a JSONArray - java

We have some code where we read a JSON file into a string and then use Json-lib to process it as follows:
// ...
JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(jsonStr);
// ...
We now have a situation where the file is actually a JSONArray (i.e. starts with [ and ends with ]). The file passes all JSON validation tests but our code raises the following exception:
java.lang.ClassCastException: net.sf.json.JSONArray cannot be cast to net.sf.json.JSONObject
We are able to get past the problem by resorting to the following hack:
// ...
JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON("{" + jsonStr + "}");
// ...
Question: Is there a way to process the file, without resorting to the hack?

Question: Is there a way to process the file, without resorting to the hack?
I am assuming that you are using JSON-lib as implied by the [json-lib] tag.
I am also assuming that you have encountered this problem in writing the unit tests for your code. (If not ... why not?)
In the JSON-lib APIs, JSONObject and JSONArray have a common supertype JSON, so you should be able to assign a JSONObject or JSONArray to a variable of type JSON. (The JSON interface has methods isObject and isArray that allow you to test if a JSON is an object or an array ... but no asObject or asArray methods.)
However, if your tests actually require a JSONObject ... you have a problem. In JSON, the "object" and "array" data structures are fundamentally different. Neither is a conceptual subtype of the other. What your "hack" is doing is wrapping the JSON array inside a JSON object. This may or may not be the correct thing to do. (I suspect it isn't. But if it is the correct thing to do, then the "hack" is a reasonable way to do it. You could also construct a JSONObject and add the parsed JSONArray to it programatically.)
If the code under test is designed / specified to work with a JSON object and not with a JSON array, then the CORRECT solution is to reject the input file as bad input, at some point.
If your code under test is designed to do the parsing, then it should throw an exception (or whatever) to reject the bad input file. Your unit test should check that it does that.
If your code under test is designed to take a (parsed) JSONObject, then the testcase (the input file containing a JSON array) is a bad testcase. Remove it ... for the purposes of this unit test.
In short, the correct solution to your problem is going to depend on what the code you are testing is supposed to do.

You can read jsonStr as JSON Object, then convert it to Java Object:
net.sf.json.JSON json = JSONSerializer.toJSON(jsonStr);
YourJavaObject jObj = null;
List<YourJavaObject> list = null;
if(json instanceof JSONObject){
jObj = (YourJavaObject)JSONObject.toBean(JSONObject.fromObject(json), YourJavaObject.class);
}else if(json instanceof JSONArray){
list = JSONArray.toList(JSONArray.fromObject(json), new YourJavaObject(), new JsonConfig());
}

Related

How do I convert a LinkedTreeMap to gson JsonObject

For a java data handler, I send properly formatted JSON, but a combination of Spring, Java deciding how to cast what it sees, and frameworks I really shouldn't go changing mangle that JSON so that once I can see it, it's turned into a LinkedTreeMap, and I need to transform it into a JsonObject.
This is not to serialize/de-serialize JSON into java objects, it's "final form" is a gson JsonObject, and it needs to be able to handle literally any valid JSON.
{
"key":"value",
"object": {
"array":[
"value1",
"please work"
]
}
}
is the sample I've been using, once I see it, it's a LinkedTreeMap that .toString() s to
{key=value, object={array=[value1, please work]}}
where you can replace "=" with ":", but that doesn't have the internal quotes for the
new JsonParser().parse(gson.toJson(STRING)).getAsJsonObject()
strategy.
Is there a more direct way to convert LinkedTreeMap to JsonObject, or a library to add the internal quotes to the string, or even a way to turn a sting into a JsonObject that doesn't need the internal quotes?
You'd typically have to serialize the object to JSON, then parse that JSON back into a JsonObject. Fortunately, Gson provides a toJsonTree method that kind of skips the parsing.
LinkedTreeMap<?,?> yourMap = ...;
JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();
Note that, if you can, just deserialize the JSON directly to a JsonObject with
gson.fromJson(theJson, JsonObject.class);

Java object from JSON input file

Hi I have a json input file as follows,
{'Latitude':'20',
'coolness':2.0,
'altitude':39000,
'pilot':{'firstName':'Buzz',
'lastName':'Aldrin'},
'mission':'apollo 11'}
How to create a java object from the json input file.
Thanks
You can use the very simple GSON library, with the Gson#fromJson() method.
Here's an example: Converting JSON to Java
There are more than one APIs that can be used. The simplest one is JSONObject
Just do the following:
JSONObject o = new JSONObject(jsonString);
int alt = o.getInt("altitude");
....
there are getXXX methods for each type. It basically stores the object as a map. This is a slow API.
You may use Google's Gson, which is an elegant and better library -- slightly more work required than JSONObject. If you are really concerned about speed, use Jackson.

JSON String to JSON in Java

I have a couple of txt files that gets some information from android's (call,messages,etc) database and stores it as a Cursor object.
I then convert the Cursor onto a JSON object which is then stored on a txt file on an SD card on the device. When I read from the file I get lines as a String like this one:
{"date":1332969098495,"duration":0,"number":"7038673588","Device_ID":"streak"}
I have to store the values of the String onto a MySQL table. Is there a way that I can convert this back onto a JSON or maybe a Map?
I thought about editing the String so the values are surrounded by a single quote and use the MySQL syntax to simply load the fields on the file.
Thanks!
You can create a JSONObject from the string that you have. That will pretty much give the same functionality as that of java.util.Map. For e.g,
String jsonStr = "json representation of your data";
JSONObject jObj = new JSONObject(jsonStr);
jObj.get(yourKeyString);
//do more with your jObj here...
Hope this helps. Refer the JSONObject documentation for more details.
You need to use JSon-lib (or) GSon libraries for this purpose.
Example GSon code would be:
YourObject obj = gson.fromJson(inputJson, YourObject.class);
Note: YourObject is java class with getter/setter.
Here is an tutorial of using GSON library to achieve typed object conversion.
http://java.sg/parsing-a-json-string-into-an-object-with-gson-easily/
Sathishpaul is correct but just to clarify :
JSONObject obj = new JSONObject(YourJSONString);
Long date = obj.getLong("date");
int duration = obj.getInt("duration");
etc..

org.json.JSONObject constructor not accepting what appears to be a valid JSON string

I have a string in an Android app that I am trying to convert into a JSONObject. The string looks like this (except longer and with actual values instead of the dummy values I entered here):
[[{"1":"a"}],[{"1a":"1a","1b":"1b"},{"2a":"2a","2b":"2b"}]]
I have entered this exact string into two online JSON validators, and both of them confirm it to be valid JSON data. So I would assume that the JSONObject constructor would be able to accept this string and convert it into a JSONObject. But when I try:
json = new JSONObject(result);
Where "result" is a String variable containing the string listed above, I get the following exception:
JSONException: A JSONObject text must begin with '{' at character 1 of [[{"1":"a"}],[{"1a":"1a","1b":"1b"},{"2a":"2a","2b":"2b"}]]
What's going on here? Is the JSONObject's parser broken?
You are trying to create a JSONObject, but what you are actually giving it is a JSONArray. Did you try creating a JSONArray instead?
Alternatively, you could wrap your array in an object so that you can create a JSONObject out of it.
I would suggest using the GSon library instead as it appears to be more full-featured.
In addition, it may be helpful to use this tool to test your data (your data is valid btw):

Converting Strings to booleans when converting XML to JSON

This block of code essentially takes a JAXB Object and turns it into a JSONObject
StringWriter stringWriter = new StringWriter();
marshaller.marshal(jaxbObj, stringWriter);
try {
JSONObject jsonObject = XML.toJSONObject(stringWriter.toString());
resp.getOutputStream().write(jsonObject.toString(2).getBytes());
} catch (JSONException e) {
throw new ServletException("Could not parse JSON",e);
}
Unfortunately, this transformation doesn't turn, say, a String like "true" into a boolean, leaving the poor front end guy to do it.
I would think that I want to somehow map over the values in the JSONObject, calling stringToValue on each. I have a feeling there is a better way. Any ideas?
Well, JAXB itself won't even produce JSON to begin with, so you are using something else in addition (maybe use it via Jersey). So maybe package in question has something.
But why try to do this with org.json objects? Just use regular Java bean with expected type, create that from whatever input bean you have. No need for magic, just explicit code.

Categories

Resources