Java reading JSON as associative array like javascript and PHP ( ['key']['subKey'] ) - java

I am writing a java program to read Json as associative array, like we do in javascript and PHP. I am 90% done but problem occurs when i try to read array from Json object.
Here is data.json file which contains student record
{
"students": {
"2334": {
"name": {
"firstname": "umer",
"lastname": "farooq"
},
"subject": {
"marks": {
"maths": {
"total": 100.0,
"obtained": 70.0
},
"computer": {
"total": 100.0,
"obtained": 96.0
}
}
},
"lang": ["java", "javascript", "C#"]
},
"1003": {
"name": {
"firstname": "yasir",
"lastname": "khan"
},
"subject": {
"marks": {
"maths": {
"total": 100.0,
"obtained": 80.0
},
"computer": {
"total": 100.0,
"obtained": 60.0
}
}
},
"lang": ["C++", "PHP", "C#"]
},
"1233": {
"name": {
"firstname": "Mubarak",
"lastname": "Amin"
},
"subject": {
"marks": {
"maths": {
"total": 100.0,
"obtained": 70.0
},
"computer": {
"total": 100.0,
"obtained": 50.0
}
}
},
"lang": ["Ruby", "javascript", "C"]
}
}
}
To fetch marks obtained by student with the id 1233 in mathematics, i would simple pass string ['students']['1233']['subject']['marks']['maths']['obtained'] to getValue() method
JSONAssociativeArrayReader parser = new JSONAssociativeArrayReader();
parser.setJSONFile(new File("data.json"));
double marksObtainedInMaths = (double) parser.getValue("['students']['1233']['subject']['marks']['maths']['obtained']");
System.out.println("Marks obtained (maths) = " + marksObtainedInMaths);
Above code produces Marks obtained (maths) = 70.0 which is correct. Problem occurs when i try to fetch array from Json file via my getArray() method.
System.out.println("languages = " + parser.getArray("['students']['1233']['lang']") );
expected output : languages = [Ruby, javascript, C]
Following error occurs when above statement is executed
Exception in thread "main" javax.script.ScriptException: TypeError: Cannot read property "lang" from undefined in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:467)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:451)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(Unknown Source)
at JSONAssociativeArrayReader.getArray(Main.java:77)
at Main.main(Main.java:30)
Caused by: <eval>:1 TypeError: Cannot read property "lang" from undefined
at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185)
at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172)
at jdk.nashorn.internal.runtime.Undefined.get(Undefined.java:157)
at jdk.nashorn.internal.scripts.Script$2$\^eval\_.:program(<eval>:1)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)
... 6 more
Here is the code for JSONAssociativeArrayReader
class JSONAssociativeArrayReader
{
private ScriptEngineManager factory;
private ScriptEngine engine;
private static final String JSON_OBJECT_NAME = "jsonObject";
private static final String JSON_ARRAY_NAME = "jsonArray";
public JSONAssociativeArrayReader() throws ScriptException
{
factory = new ScriptEngineManager();
engine = factory.getEngineByName("JavaScript");
}
public void setJSONFile(File jsonFile) throws IOException, ScriptException
{
String jsonStringFromFile = "";
if(jsonFile != null)
{
BufferedReader br = new BufferedReader(new FileReader(jsonFile));
String line = "";
while((line = br.readLine()) != null)
{
jsonStringFromFile += line;
}
}
engine.eval("var " + JSON_OBJECT_NAME + " = " + jsonStringFromFile);
}
public ArrayList<Object> getArray(String associativeArray) throws ScriptException
{
ArrayList<Object> objects = new ArrayList<>();
engine.eval("var " + JSON_ARRAY_NAME + " = " + associativeArray);
engine.eval("var arraylength = " + JSON_ARRAY_NAME + ".length");
int arrayLength = (int) engine.eval("arraylength");
for (int i = 0; i < arrayLength; i++)
{
engine.eval(" var arrayElement = " + JSON_ARRAY_NAME + "["+i+"]");
objects.add(engine.get("arrayElement"));
}
return objects;
}
public Object getValue(String associativeArray) throws ScriptException
{
return engine.eval(JSON_OBJECT_NAME+associativeArray);
}
}
What i am doing wrong ?

As far as I can tell, your issue is at
JSON_ARRAY_NAME + " = " + associativeArray);
You're forgetting the JSON_OBJECT_NAME and just assigning a var to the value of "['students']['1233']['lang']"
In other words, it needs to come to the result of
jsonObject['students']['1233']['lang']
However, in almost all JSON parsing libraries in Java, you would do something like
jsonObject.getObject("students")
.getObject("1233")
.getArray("lang")
Or using Gson/Jackson, you could easily write a model to implement
jsonObject.getStudent("1233").getLanguages()

Related

Json manipulation and conversion in Java

I have an input json like:
{
"Employee": [
{
"employee1.id": 1
},
{
"employee1.name": "John"
},
{
"employee1.address.street": "main street"
},
{
"employee1.address.pin": "123456"
},
{
"employee2.id": 2
},
{
"employee2.name": "Mike"
},
{
"employee2.address.street": "51 street"
},
{
"employee2.address.pin": "234543"
}
]
}
And I am trying to convert it into:
{
"employee1":{
"id": 1,
"name": "John",
"address": {
"street": "main street",
"pin": "123456"
}
},
"employee2":{
"id": 2,
"name": "Mike",
"address": {
"street": "51 street",
"pin": "234543"
}
}
}
I tried to split the key from input json with dot i.e. '.' and tried to iterate over to construct a map: Map<String, Object>
But the problem is the input json key depth can go beyond 2 i.e. in future the input key can be like:
{
"employee1.address.tempAddress.street": "main street"
},
{
"employee1.address.permanentAddress.street": "main street"
}
So, is there any library available to achieve this, or anything closely related to this using which I can achieve this?
The comments about the input format being "weird" (to put it politely) are spot-on: This is a convoluted way to represent simple hierarchical data.
But sometimes we have to deal with sub-optimal input formats, that's why we can fix them like this:
private static JSONObject arrayToStructure(JSONArray inputArray) {
JSONObject output = new JSONObject();
for (Object o : inputArray) {
assert o instanceof JSONObject;
JSONObject jso = (JSONObject) o;
assert jso.length() == 1;
String key = jso.keys().next();
Object value = jso.get(key);
setJsonPath(output, key, value);
}
return output;
}
private static void setJsonPath(JSONObject target, String key, Object value) {
String[] keyParts = key.split("\\.");
JSONObject parent = target;
for (int i = 0; i < keyParts.length - 1; i++) {
String keyPart = keyParts[i];
if (parent.has(keyPart)) {
parent = parent.getJSONObject(keyPart);
} else {
JSONObject child = new JSONObject();
parent.put(keyPart, child);
parent = child;
}
}
assert !parent.has(keyParts[keyParts.length - 1]);
parent.put(keyParts[keyParts.length - 1], value);
}
This code uses JSON-Java, probably better known as org.json:json.
And it can be used like this:
public static void main(String[] args) {
String input = """
[
{
"employee1.id": 1
},
{
"employee1.name": "John"
},
{
"employee1.address.street": "main street"
},
{
"employee1.address.pin": "123456"
},
{
"employee2.id": 2
},
{
"employee2.name": "Mike"
},
{
"employee2.address.street": "51 street"
},
{
"employee2.address.pin": "234543"
}
]""";
JSONArray inputArray = new JSONArray(input);
JSONObject structure = arrayToStructure(inputArray);
System.out.println(structure.toString(2));
}
Note that this code is lacking proper sanity checks (some of which I've hinted at using assert) and the nature of this "protocol" means that you can get misleading, ambiguous or straight up malicious inputs. For example nothing stops the input from having both "employee1.id": 1 and "employee1.id": 2 in there. How that is to be interpreted is up to the parser and such ambiguity is a great source of bugs and potential security issues.
Library Josson can do the transformation by one expression.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"{" +
" \"Employee\": [" +
" {" +
" \"employee1.id\": 1" +
" }," +
" {" +
" \"employee1.name\": \"John\"" +
" }," +
" {" +
" \"employee1.address.street\": \"main street\"" +
" }," +
" {" +
" \"employee1.address.pin\": \"123456\"" +
" }," +
" {" +
" \"employee2.id\": 2" +
" }," +
" {" +
" \"employee2.name\": \"Mike\"" +
" }," +
" {" +
" \"employee2.address.street\": \"51 street\"" +
" }," +
" {" +
" \"employee2.address.pin\": \"234543\"" +
" }" +
" ]" +
"}");
JsonNode node = josson.getNode("Employee.mergeObjects().unflatten('.')");
System.out.println(node.toPrettyString());
Output
{
"employee1" : {
"id" : 1,
"name" : "John",
"address" : {
"street" : "main street",
"pin" : "123456"
}
},
"employee2" : {
"id" : 2,
"name" : "Mike",
"address" : {
"street" : "51 street",
"pin" : "234543"
}
}
}

How do I modify a json string in java?

I have a json string like
{"egcnbrandcid":5555444433332220,"egcstatus":"CARD NOT ON EGC DATABASE","egcbalance":0.00}
How can I modify the string safely in java?
By safely I mean that I still need a valid json string after I'm done modifying it. In this case I would be converting the number to a string with the output looking like:
{"egcnbrandcid":"redacted","egcstatus":"CARD NOT ON EGC DATABASE","egcbalance":0.00}
It's important to note that the Json string won't always contain these same fields.
You can use JSONParser(), you don't need create java objects to save, It works like Map
public static void main(String[] args) throws Exception
{
// parsing file "JSONExample.json"
Object obj = new JSONParser().parse(new FileReader("JSONExample.json"));
// typecasting obj to JSONObject
JSONObject jo = (JSONObject) obj;
// getting firstName and lastName
String firstName = (String) jo.get("firstName");
String lastName = (String) jo.get("lastName");
System.out.println(firstName);
System.out.println(lastName);
// getting age
long age = (long) jo.get("age");
System.out.println(age);
// getting address
Map address = ((Map)jo.get("address"));
// iterating address Map
Iterator<Map.Entry> itr1 = address.entrySet().iterator();
while (itr1.hasNext()) {
Map.Entry pair = itr1.next();
System.out.println(pair.getKey() + " : " + pair.getValue());
}
// getting phoneNumbers
JSONArray ja = (JSONArray) jo.get("phoneNumbers");
// iterating phoneNumbers
Iterator itr2 = ja.iterator();
while (itr2.hasNext())
{
itr1 = ((Map) itr2.next()).entrySet().iterator();
while (itr1.hasNext()) {
Map.Entry pair = itr1.next();
System.out.println(pair.getKey() + " : " + pair.getValue());
}
}
Inspired by #Yiao Sun's answer I wrote the following recursive functions
private void modJO(JSONObject job){
Iterator keys = job.keys();
while(keys.hasNext()) {
String currentKey = (String)keys.next();
JSONObject job2 = job.optJSONObject(currentKey);
JSONArray jar = job.optJSONArray(currentKey);
// If JSON Object
if(job2 != null){
modJO(job2);
}
// If JSON Array
else if(jar != null){
modJA(jar);
}
// If JSON Property
else {
if(currentKey.equals("cid")){
try{
job.put(currentKey,"redacted");
}
catch(Exception ex){}
}
}
}
}
private void modJA(JSONArray jar){
for(int i = 0; i < jar.length(); i++){
JSONObject job = jar.optJSONObject(i);
JSONArray jar2 = jar.optJSONArray(i);
if (job != null){
modJO(job);
}
else if (jar2 != null){
modJA(jar2);
}
}
}
And I tested it on this object which should cover all possible scenarios
{
notSecret: 'jetFuelCantMeltSteelBeams',
cid: 'superSecret',
obj: { cid: 'moreSecret' },
objObj: { child: { cid: 'itsASecretToEverybody' } },
array: [1, 2, 3],
objArr: [{ cid: 'topSecret' }, { cid: 'iCantBelieveItsSecret' }],
arrArr: [[1, 2], [1, 2]],
mixed: [
{ name: 'Waldo' },
{ cid: 'unbelievablySecret' },
7,
[{ name: 'HeisenBurg' }, 9]
],
emptyObj: {},
emptyArr: []
}
Final result is
{
objObj: { child: { cid: 'redacted' } },
arrArr: [[1, 2], [1, 2]],
emptyArr: [],
array: [1, 2, 3],
obj: { cid: 'redacted' },
objArr: [{ cid: 'redacted' }, { cid: 'redacted' }],
mixed: [{ name: 'Waldo' }, { cid: 'redacted' }, 7, [{ name: 'HeisenBurg' }, 9]],
emptyObj: {},
notSecret: 'jetFuelCantMeltSteelBeams',
cid: 'redacted'
}
Here's how I called it
private String modifyJsonObject(String jsonString){
String json = "{\"notSecret\": \"jetFuelCantMeltSteelBeams\",\"cid\": \"superSecret\",\"obj\": { \"cid\": \"moreSecret\" },\"objObj\": { \"child\": { \"cid\": \"itsASecretToEverybody\" } },\"array\": [1, 2, 3],\"objArr\": [{ \"cid\": \"topSecret\" }, { \"cid\": \"iCantBelieveItsSecret\" }], \"arrArr\": [[1, 2], [1, 2]],\"mixed\": [{ \"name\": \"Waldo\" },{ \"cid\": \"unbelievablySecret\" },7,[{ \"name\": \"HeisenBurg\" }, 9]],\"emptyObj\": {},\"emptyArr\": []}";
try {
JSONObject jObject = new JSONObject(json);
modJO(jObject);
return jObject.toString();
}
catch(Exception ex){
int stop = 4;
}
return "";
}

Remove numeric tags in dynamic json using java

I have a JSON Content in a String and sometimes it has numeric tags which has to be removed.
Below is a sample JSON content
{
"Test": {
"P1": false,
P2": {
"2000": [
{
"DP": "DP TEST",
"id": "ID TEST"
}
],
"4000": [
{
"DP": "DP TEST",
"id": "ID TEST"
}
],
"5000": [
{
"DP": "DP TEST",
"id": "ID TEST"
}
],
"8000": [
{
"DP": "DP TEST",
"id": "ID TEST"
}
],
"6000": [
{
"DP": "DP TEST",
"id": "ID TEST"
}
]
},
"P3": "XYZ",
"P4": ABC,
"VL": "",
"PL": [{
"start_date": 1496480880.0,
"id": "TEST1"
}
],
},
"PS": "AMD",
"links": [{
"LOC": "en-US",
"PS": "AMD"
}, {
"LOC": "fr-CA",
"PS": "AMD"
}
]
}
In the above case "P2" tag has numeric keys and in such case we need to display it as after converting the string to JSON. Which means, we need to remove the tags which has numeric keys.
I have tried with org.json, org.json.simple and com.gson as well but nothing seems to work.
I am able to read each line using the below code snipet
public static void printJson(JsonElement jsonElement) {
// Check whether jsonElement is JsonObject or not
if (jsonElement.isJsonObject()) {
Set<Entry<String, JsonElement>> ens = ((JsonObject) jsonElement).entrySet();
if (ens != null) {
// Iterate JSON Elements with Key values
for (Entry<String, JsonElement> en : ens) {
try{
Integer.parseInt(en.getKey());
break;
}catch(NumberFormatException ex){
if("".equals(str)){
str = "\"" + en.getKey() + "\": {";
}else{
str = str + "\"" + en.getKey() + "\": {";
}
System.out.println(en.getKey() + "-----" + en.getValue());
}
printJson(en.getValue());
}
}
}
// Check whether jsonElement is Arrary or not
else if (jsonElement.isJsonArray()) {
JsonArray jarr = jsonElement.getAsJsonArray();
// Iterate JSON Array to JSON Elements
for (JsonElement je : jarr) {
printJson(je);
}
}
// Check whether jsonElement is NULL or not
else if (jsonElement.isJsonNull()) {
// print null
System.out.println("null");
}
// Check whether jsonElement is Primitive or not
else if (jsonElement.isJsonPrimitive()) {
// print value as String
if("".equals(str)){
str = "\"" + jsonElement.getAsString() + "\"";
}else{
str = str + "\"" + jsonElement.getAsString() + "\"";
}
System.out.println(jsonElement.getAsString());
}
}
But am unable to remove the numeric keyed tags. Can someone please help me with this.
If you want to strip JSONObject keys that are numeric, you can do it like this:
private static void strip(JSONObject obj) {
for (Iterator<String> keyIter = obj.keys(); keyIter.hasNext(); ) {
String key = keyIter.next();
if (key.matches("\\d+"))
keyIter.remove();
else
strip(obj.get(key));
}
}
private static void strip(Object value) {
if (value instanceof JSONObject) {
strip((JSONObject) value);
} else if (value instanceof JSONArray) {
for (Object elem : (JSONArray) value)
strip(elem);
}
}
Test
String input = new String(Files.readAllBytes(Paths.get("path/to/file.json")), StandardCharsets.US_ASCII);
JSONObject obj = new JSONObject(input);
strip(obj);
System.out.println(obj.toString(2));
Output
{
"PS": "AMD",
"Test": {
"P1": false,
"P2": {},
"P3": "XYZ",
"P4": "ABC",
"VL": "",
"PL": [{
"id": "TEST1",
"start_date": 1.49648088E9
}]
},
"links": [
{
"LOC": "en-US",
"PS": "AMD"
},
{
"LOC": "fr-CA",
"PS": "AMD"
}
]
}
I got the solution with Andreas help.
But I had another issue while working on it. It was working fine for 2-3 levels only. After 3rd level, if there are any numeric keys, they were not being removed.
I have added one more condition to check if the object is an instance of org.json.JSONObject and then check if that JSONObject has any JSONArray.
Sample code given below
if (value instanceof org.json.JSONArray) {
for (int i=0; i< ((org.json.JSONArray) value).length(); i++) {
try{
if(((org.json.JSONArray) value).get(i).getClass().getName() =="org.json.JSONObject"){
strip((JSONObject) ((org.json.JSONArray) value).get(i));
}
}catch(Exception ex){
}
}
}

Parse large json data in Java with arrays and strings in json values

The json string generated from the media server looks like this
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"albums": [
{
"albumid": 1,
"albumlabel": "",
"artist": [
"www.SongsLover.pk"
],
"artistid": [
2
],
"description": "",
"genre": [
"Pop"
],
"label": "Single 2012",
"rating": 0,
"style": [
""
],
"thumbnail": "image://music#smb%3a%2f%2fCECOTS-NAS%2fMedia%2fMusic%2fbackup%20Music%2fSissle2%2fGangnam%20Style%20.mp3/",
"title": "Single 2012",
"type": "",
"year": 0
},
{
"albumid": 164,
"albumlabel": "",
"artist": [
"ARrahman","MJ"
],
"artistid": [
146,163
],
"description": "",
"genre": [
"Soundtrack"
],
"label": "Lord of the rings",
"rating": 0,
"style": [
""
],
"thumbnail": "image://music#smb%3a%2f%2fCECOTS-NAS%2fMedia%2fMusic%2fExtras_Test%2fEnakkena%20Yenave.mp3/",
"title": "Lord of the rings",
"type": "",
"year": 2000
},{..........},{........},{........}
],
"limits": {
"end": 155,
"start": 0,
"total": 155
}
}
}
The following is the code i tried using Java. Iam getting the json response as Input stream and using jsonreader to parse the json response. But here in the above json, the artist dictionary has array values without names.
JsonReader reader = new JsonReader(new InputStreamReader(inputStream,
"UTF-8"));
ArrayList<Integer> albumId = new ArrayList<Integer>();
ArrayList<String> artistId = new ArrayList<String>();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equalsIgnoreCase("result")) {
reader.beginObject();
while (reader.hasNext()) {
String check = reader.nextName();
if (check.equalsIgnoreCase(type)) {
reader.beginArray();
int i = 0;
while (reader.hasNext()) {
i++;
reader.beginObject();
int albumid;
String artistid = null;
while (reader.hasNext()) {
name = reader.nextName();
if (name.equalsIgnoreCase("albumid")) {
albumid = reader.nextInt();
albumId.add(albumid);
} else if (name
.equalsIgnoreCase("artist")) {
reader.beginArray();
while(reader.hasNext()){
artistid = reader.nextString();
artistId.add(artistid);
}
reader.endArray();
} else {
reader.skipValue();
}
}
reader.endObject();
//}
}
Log.i(LOGCAT, Integer.toString(i));
reader.endArray();
} else {
reader.skipValue();
}
}
reader.endObject();
} else {
reader.skipValue();
}
}
reader.endObject();
So, the problem for me is how to get the array values from the artist dictionary with the above code. Please help me in this. Thanks in advance.
// Try this way,hope this will you to solve your problem...
String respone = "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":{\"albums\":[{\"albumid\":1,\"albumlabel\":\"\",\"artist\":[\"www.SongsLover.pk\"],\"artistid\":[2],\"description\":\"\",\"genre\":[\"Pop\"],\"label\":\"Single 2012\",\"rating\":0,\"style\":[\"\"],\"thumbnail\":\"image://music#smb%3a%2f%2fCECOTS-NAS%2fMedia%2fMusic%2fbackup%20Music%2fSissle2%2fGangnam%20Style%20.mp3/\",\"title\":\"Single 2012\",\"type\":\"\",\"year\":0},{\"albumid\":164,\"albumlabel\":\"\",\"artist\":[\"ARrahman\",\"MJ\"],\"artistid\":[146,163],\"description\":\"\",\"genre\":[\"Soundtrack\"],\"label\":\"Lord of the rings\",\"rating\":0,\"style\":[\"\"],\"thumbnail\":\"image://music#smb%3a%2f%2fCECOTS-NAS%2fMedia%2fMusic%2fExtras_Test%2fEnakkena%20Yenave.mp3/\",\"title\":\"Lord of the rings\",\"type\":\"\",\"year\":2000}],\"limits\":{\"end\":155,\"start\":0,\"total\":155}}}";
ArrayList<HashMap<String,Object>> albumList = new ArrayList<HashMap<String, Object>>();
try{
JSONObject responseJson = new JSONObject(respone);
JSONArray albumJsonArray = responseJson.getJSONObject("result").getJSONArray("albums");
for (int i=0;i<albumJsonArray.length();i++){
HashMap<String,Object> album = new HashMap<String, Object>();
album.put("albumid",albumJsonArray.getJSONObject(i).getString("albumid"));
album.put("albumlabel",albumJsonArray.getJSONObject(i).getString("albumlabel"));
JSONArray artistJsonArray = new JSONArray(albumJsonArray.getJSONObject(i).getString("artist"));
ArrayList<String> artistList = new ArrayList<String>();
for (int j=0;j<artistJsonArray.length();j++){
artistList.add(artistJsonArray.getString(j));
}
album.put("artist",artistList);
JSONArray artistidJsonArray = new JSONArray(albumJsonArray.getJSONObject(i).getString("artistid"));
ArrayList<String> artistidList = new ArrayList<String>();
for (int j=0;j<artistidJsonArray.length();j++){
artistidList.add(artistidJsonArray.getString(j));
}
album.put("artistid",artistidList);
album.put("description",albumJsonArray.getJSONObject(i).getString("description"));
JSONArray genreJsonArray = new JSONArray(albumJsonArray.getJSONObject(i).getString("genre"));
ArrayList<String> genreList = new ArrayList<String>();
for (int j=0;j<genreJsonArray.length();j++){
genreList.add(genreJsonArray.getString(j));
}
album.put("genre",genreList);
album.put("label",albumJsonArray.getJSONObject(i).getString("label"));
album.put("rating",albumJsonArray.getJSONObject(i).getString("rating"));
JSONArray styleJsonArray = new JSONArray(albumJsonArray.getJSONObject(i).getString("style"));
ArrayList<String> styleList = new ArrayList<String>();
for (int j=0;j<styleJsonArray.length();j++){
styleList.add(styleJsonArray.getString(j));
}
album.put("style",styleList);
album.put("thumbnail",albumJsonArray.getJSONObject(i).getString("thumbnail"));
album.put("title",albumJsonArray.getJSONObject(i).getString("title"));
album.put("type",albumJsonArray.getJSONObject(i).getString("type"));
album.put("year",albumJsonArray.getJSONObject(i).getString("year"));
albumList.add(album);
}
for (HashMap<String,Object> album:albumList){
System.out.println("Album Id : "+album.get("albumid").toString());
System.out.println("Album Label : "+album.get("albumlabel").toString());
System.out.println("Album Description : "+album.get("description").toString());
System.out.println("Label : "+album.get("label").toString());
System.out.println("Rating : "+album.get("rating").toString());
System.out.println("Thumbnail : "+album.get("thumbnail").toString());
System.out.println("Title : "+album.get("title").toString());
System.out.println("Type : "+album.get("type").toString());
System.out.println("Year : "+album.get("year").toString());
System.out.println("Artist size : "+((ArrayList<String>)album.get("artist")).size());
System.out.println("Artist Id size : "+((ArrayList<String>)album.get("artistid")).size());
System.out.println("Genre size : "+((ArrayList<String>)album.get("genre")).size());
System.out.println("Style size : "+((ArrayList<String>)album.get("style")).size());
}
}catch (Throwable e){
e.printStackTrace();
}
You can use JsonPath to extract the artist arrays.
e.g. "$.result.albums[*].artist".
JsonSurfer would be a good choice if you are handling large json because it uses streaming parser without loading whole json into the memory.
The code is short with JsonSurfer.
JsonSurfer jsonSurfer = JsonSurfer.gson();
Collection<Object> result = jsonSurfer.collectAll(inputStreamReader, "$.result.albums[*].artist");

How can I sort a JSONArray in JAVA [duplicate]

This question already has answers here:
Android how to sort JSONArray of JSONObjects
(6 answers)
Closed 9 years ago.
How to sort a JSONArray of objects by object's field?
Input:
[
{ "ID": "135", "Name": "Fargo Chan" },
{ "ID": "432", "Name": "Aaron Luke" },
{ "ID": "252", "Name": "Dilip Singh" }
];
Desired output (sorted by "Name" field):
[
{ "ID": "432", "Name": "Aaron Luke" },
{ "ID": "252", "Name": "Dilip Singh" }
{ "ID": "135", "Name": "Fargo Chan" },
];
Try this:
//I assume that we need to create a JSONArray object from the following string
String jsonArrStr = "[ { \"ID\": \"135\", \"Name\": \"Fargo Chan\" },{ \"ID\": \"432\", \"Name\": \"Aaron Luke\" },{ \"ID\": \"252\", \"Name\": \"Dilip Singh\" }]";
JSONArray jsonArr = new JSONArray(jsonArrStr);
JSONArray sortedJsonArray = new JSONArray();
List<JSONObject> jsonValues = new ArrayList<JSONObject>();
for (int i = 0; i < jsonArr.length(); i++) {
jsonValues.add(jsonArr.getJSONObject(i));
}
Collections.sort( jsonValues, new Comparator<JSONObject>() {
//You can change "Name" with "ID" if you want to sort by ID
private static final String KEY_NAME = "Name";
#Override
public int compare(JSONObject a, JSONObject b) {
String valA = new String();
String valB = new String();
try {
valA = (String) a.get(KEY_NAME);
valB = (String) b.get(KEY_NAME);
}
catch (JSONException e) {
//do something
}
return valA.compareTo(valB);
//if you want to change the sort order, simply use the following:
//return -valA.compareTo(valB);
}
});
for (int i = 0; i < jsonArr.length(); i++) {
sortedJsonArray.put(jsonValues.get(i));
}
The sorted JSONArray is now stored in the sortedJsonArray object.

Categories