I am working on a GWT app that is receiving a JSON string, and I'm having a hard time getting down to the values of each object. I'm trying to transfer the incoming JSON string into an array of objects.
Here is the JSON (from Firebug response tab), The "d" is a .NET thing (Web Service Being Consumed is C#.
{
"d": [
{
"__type": "Event",
"ID": 30,
"Bin": 1,
"Date": "\/Date(1281544749000)\/",
"Desc": "Blue with white stripes.",
"Category": "1"
},
{
"__type": "Event",
"ID": 16,
"Bin": 3,
"Date": "\/Date(1281636239000)\/",
"Desc": "Yellow with pink stripes",
"Category": "1"
}
]
}
I'm trying to parse the JSON into objects, and then insert them into an array. I'm able to use Window.alert and get the entire "d" object to echo. However, when I try to access the elements of the array, GWT debugger just crashes.
//My GWT array to receive JSON Array
ArrayList<Item> itemInfo = new ArrayList<Item>();
//Getting response JSON into something I can work with.(THIS FAILS)
JSONArray jsonValue = JSONParser.parse(incomingJsonRespone);
//Just trying to verify I'm getting values
for (int i=0; i<jsonValue.size(); i++) {
JSONValue jsonItem = = JsonValue.get(i).getString();
Window.alert(jsonItem);
itemInfo.add(jsonItem);
}
I think I have narrowed down the problem to where the JSONArray instance is being created. Is there something blatantly wrong with how I'm trying to do this, because I'm not getting much help in the way of error messages?
In response to RMorrisey's comment:
Actually, it's more convoluted :/ It would look something like this (code untested, but you should get the general idea):
JSONValue jsonValue;
JSONArray jsonArray;
JSONObject jsonObject;
JSONString jsonString;
jsonValue = JSONParser.parseStrict(incomingJsonRespone);
// parseStrict is available in GWT >=2.1
// But without it, GWT is just internally calling eval()
// which is strongly discouraged for untrusted sources
if ((jsonObject = jsonValue.isObject()) == null) {
Window.alert("Error parsing the JSON");
// Possibilites: error during download,
// someone trying to break the application, etc.
}
jsonValue = jsonObject.get("d"); // Actually, this needs
// a null check too
if ((jsonArray = jsonValue.isArray()) == null) {
Window.alert("Error parsing the JSON");
}
jsonValue = jsonArray.get(0);
if ((jsonObject = jsonValue.isObject()) == null) {
Window.alert("Error parsing the JSON");
}
jsonValue = jsonObject.get("Desc");
if ((jsonString = jsonValue.isString()) == null) {
Window.alert("Error parsing the JSON");
}
Window.alert(jsonString.stringValue()); // Finally!
As you can see, when using JSONParser you have to/should be very cautious - that's the whole point, right? To parse an unsafe JSON (otherwise, like I suggested in the comments, you should go with JavaScript Overlay Types). You get a JSONValue, check if it's really what you think it should be, say, a JSONObject, you get that JSONObject, check if it has the "xyz" key, you get a JSONValue, rinse and repeat. Not the most interesting work, but at least its safer than just calling eval() on the whole JSON :)
Attention: as Jason pointed out, prior to GWT 2.1, JSONParser used eval() internally (it only had a parse() method - GWT 2.0 javadocs vs GWT 2.1). In GWT 2.1, parse() became deprecated and two more methods were introduced - parseLenient() (uses eval() internally) and parseStrict() (the safe approach). If you really have to use JSONParser, then I'd suggest upgrading to GWT 2.1 M2, because otherwise you might as well use JSOs. As an alternative to JSONParser for untrusted sources, you could try integrating json2.js as a JSON parser via JSNI.
PS: cinqoTimo, JSONArray jsonValue = JSONParser.parse(incomingJsonRespone); obviously doesn't work because JSONParser.parse has a return type of JSONValue, not JSONArray - didn't your IDE (Eclipse + Google Plugin?) warn you? Or at least the compiler.
It looks like you don't have an array, but a single root object, whose property called 'd' is an array. I'm not familiar with that specific API, but maybe you can try retrieving a JSONObject or similar instead of an array?
Related
I have following json as string:
{
"field1":"value1",
"field2":"value2",
"field3":{
"field31":"value31",
"field32":"value32"
},
"field4":{
"field41":"value41"
}
}
What is the best and the most modern way to get from this json just value from field41, so I would return "value41". I know that I can use JSONObject but I'm wondering weather we have any other better option?
Try JSONPath
String json = "...";
String field41 = JsonPath.read(json, "$.field4.field41");
You can test it here - https://jsonpath.herokuapp.com/
If you want to generate a real object out of it you can use Gson. You need to describe the class first. There are online json to Java objects converters out there. And then you can just call:
YourObject obj = new Gson().fromJson(json,YourObject.class);
System.out.println(obj.getField4().getField41());
And there you have it!
I'm developing an app for android that communicates with a server and receives JSON responses from it. Recently I changed the responses structure to contain more information about the requests.
Initially my responses where just the response from a mysqli_query encoded to JSON by the php function json_encode, and looked like this:
[
{"id":"31","description":"Hello"},
{"id":"32","description":"World"},
]
And to retrieve the objects, I would just create a new JSONArray object by calling my_json_array=new JSONArray(response) and iterate over it.
But now, my new responses contain extra data, like this:
{
"error":false,
"idCode":0,
"message":[
{
"id":"32",
"description":"Hello"
},
{
"id":"31",
"description":"World"
}
]
}
So now, as far as I understand, I need to convert this response to a JSONObject, and then extract the message as a JSONarray object by calling my_json_object.getJSONArray("message");.
I can extract the data from the "error" and the "idCode" fields normally, but when I try to extract the JSONArray from "message" it returns null, and no exceptions are thrown except for the NullPointerException.
I've validated the JSON string here, escaped the characters that could be problematic for java like the double quotes, removed uppercases, written the response as a single line, removed the double quotes surrounding the "id" value, used single quotes instead of double quotes, used harcoded string instead of the response from the server, checked the unicode representation of the string to see if contains any invalid characters (and it looks like it doesn't) and I don't know what else to do. Something to notice: the method toString() on the object returns the string "null", and based on the toString() method of the JSONObjects, it seems like the problem comes from the JSONStringer library, and going deeper on the classes it looks like the exception that there is a nesting problem, but I can't find any problem in my JSON string.
The important part of the code:
public String getResponse(){
web_helper.sendRequest();
//everything fine over here
return web_helper.getResponse();
}
public void printData(){ throws JSONExpection
JSONObject my_json_object=new JSONObject(getResponse());
System.out.println("error: "+my_json_object.getBoolean("error"));
System.out.println("idCode: "+my_json_object.getInt("idCode"));
JSONArray my_json_array=my_json_object.getJSONArray("message");
//not sure if the next part works because my_json_array is null
for(int i=0; i<my_json_array.length(); i++){
JSONObject obj=my_json_array.getJSONObject(i);
System.out.println("id: "+obj.getInt("id"));
System.out.println("description: "+obj.getString("description"));
}
}
Any help is appreciated, thank you in advance!.
Since the Processing forum is down I hope one of you guys can help me out.
I made a Processing sketch that pulls data from an API (test here: http://www.europeana.eu/portal/api/console.html ) in JSON-format and reads some fields of this data for visualization. Everything works fine so far except when there are fields that are not bound to every JSONObject.
This is the code for the retrieval of the data:
JSONObject json;
json = loadJSONObject("data.json"); // loading my JSON file into the object
JSONArray CHOData = json.getJSONArray("items"); // array of the items I want data from
for (int i = 0; i < CHOData.size(); i++) {
JSONObject CHO = CHOData.getJSONObject(i); // get a specific item
JSONArray previewObj = CHO.getJSONArray("edmPreview"); // this field is an array, so I need to store it in a JSONArray object first
String[] previewArray = previewObj.getStringArray(); // here I store it in my actual string array
String preview = previewArray[0]; // I only need the first element
}
As you can see, I want the first string of the "edmPreview" array in the object. When I run the sketch, I get an error: "JSONObject["edmPreview"] not found."
This is of course because not every item has such an object. But how can I test if there is an object with this name in an item? I tried with if(CHO.getJSONObject("edmPreview") != null), but same error. Is there a way to look into the JSONObject and check the data values for something called "edmPreview"? There is no such function explained in the Processing reference.
The JSON file essentially looks as follows:
{
"items": [
{
"id": "someID",
"edmPreview": [
"http://europeanastatic.eu/api/image?uri=someimage.jpg"
],
// some other fields
}, // some other items
]
}
I'm new to this JSON-stuff, so maybe I miss something important... Thanks for the help!
So I found the answer myself, but not in the Processing reference, but in the actual reference for the JSONObject class in Java (http://www.json.org/javadoc/org/json/JSONObject.html). I tried some of the methods there and found that hasKey() (which is actually something I came up with myself, combining the method "has()" with the term "key", pure coincidence) as a boolean value works very well:
String preview = "";
if (CHO.hasKey("edmPreview")) {
JSONArray previewObj = CHO.getJSONArray("edmPreview");
String[] previewArray = previewObj.getStringArray();
preview = previewArray[0];
}
So now I learned that Processing is essentially just Java and sometimes not every method is written in the Reference. :-)
I am using Jackson 2.2 to read a very large JSON string into a Java object. Using ObjectMapper, I read everything into the memory and transform the JSON string to object. This is all happening in memory, so the entire JSON string is loaded into the memory and transformed into the object.
If there a more memory efficient way of doing it? i.e. without loading the entire JSON string into the memory, I should still be able to load the object.
Yes, you typically use so-called "streaming" API to iterate over JSON tokens; and once positioned over first token of the value you want (START_OBJECT for JSON Objects), use data-binding API, passing reader/parser for it to use. Details of this depend on library. I know that at least following support this mode of operation:
Jackson
Gson
Genson
For Jackson, basic Streaming API usage is talked about here (for example); but one thing that does not show is how to bind objects once you are positioned at the right place.
So assuming JSON like:
{ "comment" : "...",
"values" : [
{ ... value object 1 ... },
{ ... value object 2. ... }
]
}
you could do:
ObjectMapper mapper = new ObjectMapper();
JsonParser jp = mapper.getFactory().createJsonParser(jsonInput);
jp.nextToken(); // will return START_OBJECT, may want to verify
while (jp.nextValue() != null) { // 'nextValue' skips FIELD_NAME token, if any
String fieldName = jp.getCurrentName();
if ("values".equals(fieldName)) {
// yes, should now point to START_ARRAY
while (jp.nextToken() == JsonToken.START_OBJECT) {
ValueObject v = mapper.readValue(jp, ValueObject.class);
// process individual value in whatever way to you want to...
}
} else if ("comment".equals(fieldName)) {
// handle comment?
} // may use another else to catch unknown fields, if any
}
jp.close();
and that should let you only bind one object at a time.
I am passing a json object from javascript to a java servlet using ajax.
var jsonObj = JSON.stringify(objArray); //Then I pass it to Java using ajax.
In my Java I am getting the json string from the request, then creating a jsonarray, then looping through that array and i'm getting errors when trying to pull one of the json objects from the array.
String dataObj = request.getParameter("obj");
String sql = request.getParameter("sql");
ArrayList<Object> returnArray = new ArrayList<Object>();
int key;
//Get type of object being passed.
JSONArray jsonArray = JSONArray.fromObject(dataObj);
for(int i=0; i<jsonArray.size(); i++) {
String obj = new Gson().toJson(jsonArray.getJSONObject(i)); //This is where i'm getting an error
String className = getClassName(jsonArray.getJSONObject(i));
Class targetClass = null;
try {
targetClass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Create Object
Object data = new Gson().fromJson(obj, targetClass);
I'm posting the relevant code, the for loop isn't closed because the rest of the code is quite long, and this is the part where i'm getting the error.
net.sf.json.JSONException: JSONArray[0] is not a JSONObject.
Here is what the json array looks like when its passed in from javascript. This is a println of the jsonArray object.
[{"number":"(123) 456-7050","type":"Home","contactId":1,"id":16662,"className":"beans.PhoneNumber","position":0}]
With one object in it, this code works. But as soon as I get 2 or more, my error comes up.
[[{"number":"(123) 456-7050","type":"Home","contactId":1,"id":16662,"className":"beans.PhoneNumber","position":1},{"number":"(555) 555-1233","type":"Mobile","contactId":1,"id":16656,"className":"beans.PhoneNumber","position":0},{"number":"(999) 999-9999","type":"Home","contactId":1,"id":16664,"className":"beans.PhoneNumber","position":3},{"number":"(222) 222-2222","type":"Home","contactId":1,"id":16666,"className":"beans.PhoneNumber","position":4}]]
It almost looks like when i'm passing more than one object, it create an array of an array, which could be why its not working. But how do I avoid doing that when i'm passing a jsonarray from javascript? Using just the dataObj I have no access to size or get to loop through it.
[
[
{
"number":"(123) 456-7050","type":"Home",
"contactId":1,
"id":16662,
"className":"beans.PhoneNumber",
"position":1
},
{
"number":"(555) 555-1233",
"type":"Mobile",
"contactId":1,
"id":16656,
"className":"beans.PhoneNumber",
"position":0
},
{
"number":"(999) 999-9999",
"type":"Home",
"contactId":1,
"id":16664,
"className":"beans.PhoneNumber",
"position":3
},
{
"number":"(222) 222-2222",
"type":"Home",
"contactId":1,
"id":16666,
"className":"beans.PhoneNumber",
"position":4
}
]
]
This is not an array of objects. This is an array of arrays of objects. According to your description, you are expecting something like the following to be fed to your Java:
[{"foo":"bar"}, {"bar":"baz"}]
But you are really trying to parse:
[[{"foo":"bar"}, {"bar":"baz"}]]
I am not completely sure, because you have not shared the json that you are trying to parse, but the most probable error you have is just what it says: the first element of the array is not JSONObject. Note that string values, lons and booleans are not JSONObjects. I would suggest you to use the more genereal JSONArray.get and check instance of what class it is. Maybe this can head you to the problem with the json you have. If I got it completely wrong - write back and I will try to help. In such a case it will be still useful to share the results of the proposed experiment.
EDIT:
This is double array -> maybe you using getJSONArray(int index) will help you. as the other answer mentioned - this is array of arrays. Also consider changing the javascript to reduce the level of arrays included.