View Full Version : Handling nested values in JSON by JSONReader
siva.sajja
23 Mar 2009, 2:45 AM
Hi,
I am finding it difficult to figure out how nested values can be handled using JSONReader and ModelType. Only solution I can think of is using my own JSON reader instead of GXT's JSONReader. Please share your views.
Sample JSON:
{items:[{name:"Group1", properties:{p1:"1",p2:"2"}}]}
Thanks,
Siva.
mraible
1 Apr 2009, 11:08 AM
I ended up writing my own method with String[] support. I agree that it'd be great if JsonReader supported arrays and objects.
/**
* Better read() method than JsonReader since this one supports String[]
*/
private ListLoadResult readWithArraySupport(C loadConfig, Object data) {
ModelType modelType = model.getModelType();
JSONObject jsonRoot = null;
if (data instanceof JavaScriptObject) {
jsonRoot = new JSONObject((JavaScriptObject) data);
} else {
jsonRoot = (JSONObject) JSONParser.parse((String) data);
}
JSONArray root = (JSONArray) jsonRoot.get(modelType.root);
int size = root.size();
ArrayList<ModelData> models = new ArrayList<ModelData>();
for (int i = 0; i < size; i++) {
JSONObject obj = (JSONObject) root.get(i);
ModelData model = newModelInstance();
for (int j = 0; j < modelType.getFieldCount(); j++) {
DataField field = modelType.getField(j);
String map = field.map != null ? field.map : field.name;
JSONValue value = obj.get(map);
if (value == null) continue;
if (value.isArray() != null) {
JSONArray array = value.isArray();
if (field.type.equals(String[].class)) {
String[] values = new String[array.size()];
for (int k = 0; k < array.size(); k++) {
values[k] = array.get(k).isString().stringValue();
}
model.set(field.name, values);
}
} else if (value.isBoolean() != null) {
model.set(field.name, value.isBoolean().booleanValue());
} else if (value.isNumber() != null) {
if (field.type != null) {
Double d = value.isNumber().doubleValue();
if (field.type.equals(Integer.class)) {
model.set(field.name, d.intValue());
} else if (field.type.equals(Long.class)) {
model.set(field.name, d.longValue());
} else if (field.type.equals(Float.class)) {
model.set(field.name, d.floatValue());
} else {
model.set(field.name, d);
}
} else {
model.set(field.name, value.isNumber().doubleValue());
}
} else if (value.isObject() != null) {
// nothing
} else if (value.isString() != null) {
String s = value.isString().stringValue();
if (field.type != null) {
if (field.type.equals(Date.class)) {
if (field.format.equals("timestamp")) {
Date d = new Date(Long.parseLong(s) * 1000);
model.set(field.name, d);
} else {
DateTimeFormat format = DateTimeFormat.getFormat(field.format);
Date d = format.parse(s);
model.set(field.name, d);
}
}
} else {
model.set(field.name, s);
}
} else if (value.isNull() != null) {
model.set(field.name, null);
}
}
models.add(model);
}
ListLoadResult result = newLoadResult(loadConfig, models);
if (result instanceof PagingLoadResult) {
PagingLoadResult r = (PagingLoadResult) result;
int tc = getTotalCount(jsonRoot);
if (tc != -1) {
r.setTotalLength(tc);
}
}
return result;
}
tsegismont
2 Apr 2009, 12:28 PM
mraible,
I had the same idea but I've chosen to put the raw JSONArray / JSONObject in the model.
Like this the reader become reusable: you just have to write another ModelType for your nested array / object.
Regards
siva.sajja
3 Apr 2009, 12:53 AM
Looks like this is a obvious requirement as most people use nested JSON/XML data otherwise it is very limiting. I am really surprised that this is not supported in GXT and this make the use of readers really difficult.
Even if I implement my own reader by duplicating read() method with additional code, I have to face its wrath while updating GXT versions later if they change something in their JSONReader.
I am a premium member and posted it in their premium forums and that didn't even help to get their notice. Can someone get a support member to answer this thread ?
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.