I am trying to parse a JSONObject.
This JSONObject has a JSONArray in it, and it has another JSONArray inside of JSONArray.
The json form that I am trying to parse is as below.
{
"phone":"01029093199",
"store_id":"1",
"orders":[
{
"menu_id":"4",
"menu_defaultprice":"1500",
"extraorders":[
{
"extra_id":"1",
"extra_price":"0",
"extra_count":"1"
},
{
"extra_id":"38",
"extra_price":"300",
"extra_count":"2"
}
]
},
{
"menu_id":"4",
"menu_defaultprice":"1500",
"extraorders":[
{
"extra_id":"2",
"extra_price":"0",
"extra_count":"1"
},
{
"extra_id":"19",
"extra_price":"500",
"extra_count":"1"
}
]
},
{
"menu_id":"6",
"menu_defaultprice":"2000",
"extraorders":[
{
"extra_id":"6",
"extra_price":"0",
"extra_count":"1"
},
{
"extra_id":"21",
"extra_price":"500",
"extra_count":"1"
},
{
"extra_id":"41",
"extra_price":"300",
"extra_count":"1"
}
]
}
]
}
The code below is what I have tried before.
#RestController
public class OrderApiController {
private OrderService orderService;
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
#PostMapping("/OrderInsert.do")
public void insertOrder(#RequestBody JSONObject jsonObject) {
JSONParser jsonParser = new JSONParser();
System.out.println(jsonObject);
System.out.println(jsonObject.get("phone")); // phone 가져오기 성공
System.out.println(jsonObject.get("store_id")); // store_id 가져오기 성공
System.out.println("==========JSONArray Parsing start=========");
ArrayList<JSONArray> jsonArrayList = (ArrayList<JSONArray>)jsonObject.get("orders");
for(int i = 0; i < jsonArrayList.size(); i++) {
System.out.println(jsonArrayList.get(i)); // SUCCESS
String temp = jsonArrayList.get(i).toJSONString(); // WHERE ERROR HAPPENS
System.out.println(temp);
// Tried below code to remove "[", "]" from JSONArray, but not working.
// Error message was same as the message shown from line 37.
//String jsonString = temp.substring(1, temp.length()-1);
//System.out.println(jsonString);
// org.json.JSONObject jTemp = new org.json.JSONObject(jsonArrayList.get(i));
// System.out.println(jTemp); --> prints {} (empty JSONObject)
// System.out.println("menu_id : " + jTemp.getInt("menu_id")); // Not Working
}
}
}
The error shown is ..
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.json.simple.JSONArray
Additionally, I am using this json module dependency.
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20200518</version>
</dependency>
I knew that if I print something on console using System.out.println(OBJECT), the OBJECT's toString()
method is called. So I tried to call toString() , and that gave me the ClassCastException exception.
Error is in fact at ArrayList<JSONArray> jsonArrayList = (ArrayList<JSONArray>)jsonObject.get("orders");
Instead of casting JSONArray to ArrayList, you can traverse JSONArray and read its attributes. Your code can be changed something like.
#PostMapping("/OrderInsert.do")
public void insertOrder(#RequestBody JSONObject jsonObject) {
System.out.println(jsonObject);
System.out.println(jsonObject.get("phone")); // phone 가져오기 성공
System.out.println(jsonObject.get("store_id")); // store_id 가져오기 성공
System.out.println("==========JSONArray Parsing start=========");
JSONArray orders = jsonObject.getJSONArray("orders");
for(int i = 0; i < orders.length(); i++) {
System.out.println(orders.get(i)); // SUCCESS
String temp = orders.get(i).toString();
System.out.println(temp);
// Travserse further json
JSONObject order = orders.getJSONObject(i);
System.out.println(order.get("menu_defaultprice"));
System.out.println(order.get("menu_id"));
JSONArray extraorders = order.getJSONArray("extraorders");
for(int j = 0; j < extraorders.length(); j++) {
JSONObject extraOrder = extraorders.getJSONObject(j);
System.out.println(extraOrder.get("extra_id"));
System.out.println(extraOrder.get("extra_price"));
System.out.println(extraOrder.get("extra_count"));
}
}
}
You are incorrectly fetching the orders. It should be stored in JSONArray, and NOT ArrayList
Replace:
ArrayList<JSONArray> jsonArrayList = (ArrayList<JSONArray>)jsonObject.get("orders");
With:
JSONArray jsonArrayList = jsonObject.getJSONArray("orders");
Now, you can iterate JSONArray like this
for(int i = 0; i < jsonArrayList.length(); i++) {
System.out.println(jsonArrayList.get(i)); // SUCCESS
String temp = jsonArrayList.get(i).toJSONString();
System.out.println(temp);
}
Related
Replacing a value in a javax.json.JsonObject ist not possible directly because javax.json.JsonObject implements an immutable map. In order to do that you have to create a new JsonObject and copy the values from the original one into the new one taking care of replacing the value you want to replace.
I found examples of how to do that with "simple" JsonObject, where there are no nested JsonObjects. What I'm looking for is a general replace implementation where I pass a JsonObject, the attribute name and the new value. This method should "traverse" the JsonObject and replace the attribute (wherever in the object hierarchy it is) and leave the others attributes unchanged.
For ex. this is my original JsonObject
{
"Attr1":number1,
"Attr2":number2,
"Attr3":number3,
"Attr4":[
"string1"
],
"Attr5":[
{
"Attr6":[
{
"Attr7":"string2",
"Attr8":"string3",
"$Attr9":number4
},
{
"Attr7":"string4",
"Attr8":"string5",
"Attr9":number5
}
],
"Attr10":number6,
"Attr14":{
"Attr10":"string6",
"Attr11":"string7",
"Attr12":"string8"
},
"Attr13":[
"string9",
"string10"
],
"Attr14":"string11"
}
]
}
and I want to replace the Attr6 with just an array of strings instead of an array of JsonObjects:
"Attr6":["newString1","newString2"],
The corresponding call could be something like replaceValue(JsonObject jObj, String attrName, JsonValue newValue)) where 'jObj' is the entire Json, 'attrName' is 'Attr6' and 'newValue' is a JsonArray containing the two strings.
Can someone point me to an example where such a feature is implemented or help me with it?
I tried by myself with this, but it doesn't really work because the builder is re-created on every recursive iteration (or just more probably because it is all wrong... :) )
public static JsonObject replaceValue( final JsonObject jsonObject, final String jsonKey, final JsonValue jsonValue )
{
JsonObjectBuilder builder = Json.createObjectBuilder();
if(jsonObject == null)
{
return builder.build();
}
Iterator<Entry<String, JsonValue>> it = jsonObject.entrySet().iterator();
while (it.hasNext())
{
#SuppressWarnings( "rawtypes" )
JsonObject.Entry mapEntry = it.next();
if (mapEntry.getKey() == jsonKey)
{
builder.add(jsonKey, jsonValue);
}
else if (ValueType.STRING.equals(((JsonValue) mapEntry.getValue()).getValueType()) || ValueType.NUMBER.equals(((JsonValue) mapEntry.getValue()).getValueType()) || ValueType.TRUE.equals(((JsonValue) mapEntry.getValue()).getValueType()) ||
ValueType.FALSE.equals(((JsonValue) mapEntry.getValue()).getValueType()) || (JsonValue) mapEntry.getValue() == null || "schemas".equalsIgnoreCase((String) mapEntry.getKey()))
{
builder.add(mapEntry.getKey().toString(), (JsonValue) mapEntry.getValue());
}
else if (ValueType.OBJECT.equals(((JsonValue) mapEntry.getValue()).getValueType()))
{
JsonObject modifiedJsonobject = (JsonObject) mapEntry.getValue();
if (modifiedJsonobject != null)
{
replaceValue(modifiedJsonobject, jsonKey, jsonValue);
}
}
else if (ValueType.ARRAY.equals(((JsonValue) mapEntry.getValue()).getValueType()))
{
for (int i = 0; i < ((JsonValue) mapEntry.getValue()).asJsonArray().size(); i++)
{
replaceValue((JsonObject) ((JsonValue) mapEntry.getValue()).asJsonArray().get(i), jsonKey, jsonValue);
}
}
}
return builder.build();
}
This is an alternative approach to solving the problem, one which uses the streaming parser provide by javax.json.stream.JsonParser. This generates a stream of tokens from the JSON source, with javax.json.stream.JsonParser.Event values which describe the type of token (e.g. START_OBJECT, KEY_NAME, and so on).
Most importantly for us, there are skipObject() and skipArray() methods on the parser, which allow us to cut out the unwanted section of our source JSON.
The overall approach is to build a new version of the JSON, token-by-token, as a string, substituting the replacement section when we reach the relevant location (or multiple locations) in the JSON.
Finally, we convert the new string back to an object, so we can pretty-print it.
There is no recursion used in this approach.
import java.io.IOException;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.json.JsonObject;
import javax.json.JsonWriterFactory;
import javax.json.stream.JsonGenerator;
public class StreamDemo {
public static void doStream() throws IOException {
JsonParser jsonParser = Json.createParser(new StringReader(JSONSTRING));
StringBuilder sb = new StringBuilder();
Event previous = null;
String targetKeyName = "Attr6";
String replacement = "[\"newString1\",\"newString2\"]";
// This event reflects the end of the "replacement" string - namely "]".
// We need this because this event may be different from the replaced event.
Event replacementPreviousEvent = Event.END_ARRAY;
// Used when we find the target key for replacement:
boolean doReplacement = false;
while (jsonParser.hasNext()) {
Event event = jsonParser.next();
if (doReplacement) {
// Skip over the structure we want to replace:
if (event.equals(Event.START_OBJECT)) {
jsonParser.skipObject();
} else if (event.equals(Event.START_ARRAY)) {
jsonParser.skipArray();
}
// Write the replacement fragment here:
sb.append(replacement);
// Move to the next event in the stream:
event = jsonParser.next();
previous = replacementPreviousEvent;
doReplacement = false;
}
if (Event.KEY_NAME.equals(event)
&& jsonParser.getString().equals(targetKeyName)) {
doReplacement = true;
}
switch (event) {
case START_OBJECT:
if (Event.END_OBJECT.equals(previous)) {
sb.append(",");
}
sb.append("{");
break;
case END_OBJECT:
sb.append("}");
break;
case START_ARRAY:
sb.append("[");
break;
case END_ARRAY:
sb.append("]");
break;
case KEY_NAME:
sb = previousWasAValue(previous, sb);
sb = previousWasAnEnd(previous, sb);
sb.append("\"").append(jsonParser.getString()).append("\":");
break;
case VALUE_STRING:
sb = previousWasAValue(previous, sb);
sb.append("\"").append(jsonParser.getString()).append("\"");
break;
case VALUE_NUMBER:
sb = previousWasAValue(previous, sb);
if (jsonParser.isIntegralNumber()) {
sb.append(jsonParser.getLong());
} else {
sb.append(jsonParser.getBigDecimal().toPlainString());
}
break;
case VALUE_TRUE:
sb = previousWasAValue(previous, sb);
sb.append("true");
break;
case VALUE_FALSE:
sb = previousWasAValue(previous, sb);
sb.append("false");
break;
case VALUE_NULL:
sb = previousWasAValue(previous, sb);
sb.append("null");
break;
default:
break;
}
previous = event;
}
// At the end, pretty-print the new JSON:
JsonObject modifiedObject = Json.createReader(new StringReader(sb.toString())).readObject();
Map<String, Boolean> config = new HashMap<>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
String jsonString;
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
try ( Writer writer = new StringWriter()) {
writerFactory.createWriter(writer).write(modifiedObject);
jsonString = writer.toString();
}
System.out.println(jsonString);
}
private static StringBuilder previousWasAValue(Event previous, StringBuilder sb) {
// The current value follows another value - so a separating comma is needed:
if (Event.VALUE_STRING.equals(previous)
|| Event.VALUE_NUMBER.equals(previous)
|| Event.VALUE_TRUE.equals(previous)
|| Event.VALUE_FALSE.equals(previous)
|| Event.VALUE_NULL.equals(previous)) {
sb.append(",");
}
return sb;
}
private static StringBuilder previousWasAnEnd(Event previous, StringBuilder sb) {
// The current key follows the end of an object or an array, so a
// separating comma is needed:
if (Event.END_OBJECT.equals(previous)
|| Event.END_ARRAY.equals(previous)) {
sb.append(",");
}
return sb;
}
private static final String JSONSTRING
= """
{
"Attr0": null,
"Attr1": true,
"Attr2": false,
"Attr3": 3,
"Attr4": [
"string1"
],
"Attr5": [{
"Attr6": [{
"Attr7": "string2",
"Attr8": "string3",
"Attr9": 4
},
{
"Attr7": "string4",
"Attr8": "string5",
"Attr9": 5
}
],
"Attr10": 6,
"Attr14": {
"Attr10": "string6",
"Attr11": "string7",
"Attr12": "string8"
},
"Attr13": [
"string9",
123.45,
false
],
"Attr15": "string11"
}]
}
""";
}
After having taken a cue from Kolban's answer in this post Convert a JSON String to a HashMap I should have found a solution:
public class JsonUtils
{
public static JsonObject replaceValue( final JsonObject jsonObject, final String jsonKey, final Object jsonValue )
{
JsonObjectBuilder builder = Json.createObjectBuilder();
if (jsonObject != JsonObject.NULL)
{
builder = replace(jsonObject, jsonKey, jsonValue, builder);
}
return builder.build();
}
private static JsonObjectBuilder replace( final JsonObject jsonObject, final String jsonKey, final Object jsonValue, final JsonObjectBuilder builder )
{
Iterator<Entry<String, JsonValue>> it = jsonObject.entrySet().iterator();
while (it.hasNext())
{
#SuppressWarnings( "rawtypes" )
JsonObject.Entry mapEntry = it.next();
String key = mapEntry.getKey().toString();
Object value = mapEntry.getValue();
if (key.equalsIgnoreCase(jsonKey))
{
if (jsonValue instanceof String)
{
builder.add(jsonKey, (String) jsonValue);
}
else
{
builder.add(jsonKey, (JsonValue) jsonValue);
}
// here you can add the missing casting you need
continue;
}
if (value instanceof JsonArray)
{
value = toJsonArray((JsonArray) value, jsonKey, jsonValue, builder);
}
else if (value instanceof JsonObject)
{
JsonObjectBuilder newBuilder = Json.createObjectBuilder();
value = replace((JsonObject) value, jsonKey, jsonValue, newBuilder);
if (value instanceof JsonObjectBuilder)
{
value = ((JsonObjectBuilder) value).build();
}
}
builder.add(key, (JsonValue) value);
}
return builder;
}
private static JsonArray toJsonArray( final JsonArray array, final String jsonKey, final Object jsonValue, final JsonObjectBuilder builder )
{
JsonArrayBuilder jArray = Json.createArrayBuilder();
for (int i = 0; i < array.size(); i++)
{
Object value = array.get(i);
if (value instanceof JsonArray)
{
value = toJsonArray((JsonArray) value, jsonKey, jsonValue, builder);
}
else if (value instanceof JsonObject)
{
JsonObjectBuilder newBuilder = Json.createObjectBuilder();
value = replace((JsonObject) value, jsonKey, jsonValue, newBuilder);
if (value instanceof JsonObjectBuilder)
{
value = ((JsonObjectBuilder) value).build();
}
}
jArray.add((JsonValue) value);
}
return jArray.build();
}
Just keep in mind that this works if the key you want to replace is unique in the whole JsonObject.
Any improvement is more than appreciated...
If you don't want to use the streaming API (as used in my other answer), I think you can achieve a more compact approach - which is similar to yours - using JsonObjectBuilder and JsonOArrayBuilder, together with recursion:
private static JsonStructure iterate(final JsonStructure json) {
if (json.getValueType().equals(ValueType.OBJECT)) {
JsonObjectBuilder builder = Json.createObjectBuilder();
json.asJsonObject().forEach((key, value) -> {
switch (value.getValueType()) {
case OBJECT:
if (key.equals(targetKey)) {
builder.add(key, replacementJson);
} else {
builder.add(key, iterate(value.asJsonObject()));
} break;
case ARRAY:
if (key.equals(targetKey)) {
builder.add(key, replacementJson);
} else {
builder.add(key, iterate(value.asJsonArray()));
} break;
default:
if (key.equals(targetKey)) {
builder.add(key, replacementJson);
} else {
builder.add(key, value);
} break;
}
});
return builder.build();
} else if (json.getValueType().equals(ValueType.ARRAY)) {
JsonArrayBuilder builder = Json.createArrayBuilder();
json.asJsonArray().forEach((value) -> {
switch (value.getValueType()) {
case OBJECT:
builder.add(iterate(value.asJsonObject()));
break;
case ARRAY:
builder.add(iterate(value.asJsonArray()));
break;
default:
builder.add(value);
break;
}
});
return builder.build();
}
return null;
}
Personally, it's harder for me to read this recursive code than it is for me to read the streaming code in my other answer. But it certainly more concise.
It works by iterating down into the nested levels of each JSON object and array, and then builds a copy of the original data from the deepest nested levels outwards. When it finds the specified replacement key, it uses the related replacement JSON as the key's value.
The above method can be invoked as follows - which pretty-prints the end result:
final JsonStructure jsonOriginal = Json.createReader(new StringReader(JSONSTRING)).readObject();
final JsonStructure jsonCopy = iterate(jsonOriginal);
Map<String, Boolean> config = new HashMap<>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
String jsonString;
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
try ( Writer writer = new StringWriter()) {
writerFactory.createWriter(writer).write(jsonCopy);
jsonString = writer.toString();
}
System.out.println(jsonString);
For my replacement JSON I used this, showing some test data examples:
private final static String targetKey = "Attr6";
//private final static JsonStructure replacementJson = Json.createArrayBuilder()
// .add("newString1")
// .add("newString2").build();
private final static JsonStructure replacementJson = Json.createObjectBuilder()
.add("newkey1", "newString1")
.add("newkey2", "newString2").build();
So, using the same starting JSON as in my other answer, this code produces the following:
{
"Attr0": null,
"Attr1": true,
"Attr2": false,
"Attr3": 3,
"Attr4": [
"string1"
],
"Attr5": [
{
"Attr6": {
"newkey1": "newString1",
"newkey2": "newString2"
},
"Attr10": 6,
"Attr14": {
"Attr10": "string6",
"Attr11": "string7",
"Attr12": "string8"
},
"Attr13": [
"string9",
123.45,
false
],
"Attr15": "string11"
}
]
}
I was trying to get some information from a different class in java using JSONArrays and JSONObjects but for some reason I get very weird results.
My Info.java class I have:
public JSONArray getSpawnedPets() {
JSONArray petsArray = new JSONArray();
JSONObject petO = new JSONObject();
boolean spawned = false;
for (int i = 0; i <= 3; i++) {
spawned = true;
if (spawned) {
petO.put("petID", i);
petO.put("petOwner", "owner"+i);
petO.put("petName", "name");
petO.put("color", "s");
petO.put("particle", "s");
petsArray.add(petO);
}
}
return petsArray;
}
On my Main.java class I have:
public class main {
public static void main(String[] args) {
JSONArray petsArray = new JSONArray();
Info in = new Info();
petsArray = In.getSpawnedPets();
if (petsArray != null) {
for (int i = 0; i < petsArray.size(); i++) {
JSONObject po = (JSONObject) petsArray.get(i);
System.out.println("PetInfo:");
System.out.println(po.get("petID")+":");
System.out.println(""+po.get("petName"));
System.out.println(""+po.get("petOwner"));
}
}
}
}
The results were supposed to be increasing but yet I get this:
PetInfo:
3:
name
owner3
PetInfo:
3:
name
owner3
PetInfo:
3:
name
owner3
PetInfo:
3:
name
owner3
Did I do something wrong? I can't find my problem, the same code but not using classes works, but I have to use classes for it.
Cheers.
Create jsonobject in every iteration otherwise , there is only one JSONObject JSONObject petO = new JSONObject(); which is being updated in every iteration of loop
JSONArray petsArray = new JSONArray();
JSONObject petO;
//boolean spawned = false; // no need of it
for (int i = 0; i <= 3; i++) {
//spawned = true;
//if (spawned) { // no need of it , has no effect, always true
petO = new JSONObject();
// ^^^^^^^^^^^^^^^^^
petO.put("petID", i);
petO.put("petOwner", "owner"+i);
petO.put("petName", "name");
petO.put("color", "s");
petO.put("particle", "s");
petsArray.add(petO);
//}
}
Note : Since spawned is a local variable and will be set to true in first iteration and has no effect in code so there is no need of if
Im working on an app where Im parsing JSON file and get the strings from it, but there is one String I have no idea why cant I get it into my activity.
the String is Object > Array > String
I have 2 activities and 1 model.
MainActivity: where Im parsing the JSON.
DetailActivity: where I need the String.
PostModel: a model where I have all setter and getter.
JSON:
{
"status":"ok",
"count":10,
"count_total":184,
"pages":19,
"posts":[
{ },
{
"id":2413,
,
"categories":[
{
"id":100,
"slug":"logging",
"title":"logging",
"description":"",
"parent":0,
"post_count":1
}
],
"comments":[
{
"id":3564,
"content":"<p>\u47 <\/p>\n",
"parent":0
}
],
"comment_count":1,
"thumbnail":"http:\/\/www.5.com\/wtent\g",
"custom_fields":{
"dsq_thread_id":[
"2365140"
],
"videoID":[
"--ffwf92jvDFy"
]
},
"thumbnail_images":{
"full":{
"url":"http:\/\/www.5.com\/jpg",
"width":727,
"height":454
},
"thumbnail":{
"url":"http:\/\/www.5.com\/wp-con50.jpg",
"width":150,
"height":150
}
}
}
]
}
PostModel:
private List<VidCast> videoIDList;
private String videoID;
public String getVideoID() {
return videoID;
}
public void setVideoID(String videoID) {
this.videoID = videoID;
}
public List<VidCast> getvideoIDList() { return videoIDList; }
public void setvideoIDList(List<VidCast> videoIDList) {
this.videoIDList = videoIDList;
}
public static class VidCast {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
MainActivity:
List<PostModel.VidCast> vidCasts = JsonPath.parse(URL_TO_HIT).read("$.posts.[*].custom_fields.[*].videoID[*]");
vidCasts = new ArrayList<>();
for (int s = 0 ; s < finalObject.getJSONArray("custom_fields").length() ; s++){
PostModel.VidCast vidCast = new PostModel.VidCast();
vidCast.setName(videoID);
vidCasts.add(vidCast);
}
postModel.setvideoIDList(vidCasts);
// adding the final object in the list
postModelList.add(postModel);
}
return postModelList;
}
}
DetailActivity:
StringBuffer stringBuffer = new StringBuffer();
for(PostModel.CategoryCast categoryCast : postModel.getCategoryCastList()){
stringBuffer.append(categoryCast.getName() + ", ");
}
StringBuffer videoStringBuffer = new StringBuffer();
for(PostModel.VidCast videoIDList : postModel.getvideoIDList()) {
videoStringBuffer.append(videoStringBuffer.toString());
}
At the last file is where I need to get the <> String. I spent a lot of time I just cant figure it out how I can iterate over array inside an object.
Thanks in advance!
__________update________
I managed to parse it that way :
JSONObject customFields = finalObject.getJSONObject("custom_fields");
JSONArray vidCastsJson = customFields.getJSONArray("videoID");
List<PostModel.VidCast> videoIds = new ArrayList<>();
for (int s = 0 ; s < vidCastsJson.length() ; s++){
PostModel.VidCast vidCast = new PostModel.VidCast();
vidCast.setName(vidCastsJson.optString(s));
videoIds.add(vidCast);
String videoID = String.valueOf(vidCastsJson);
vidCast.setName(videoID);
and I use Stringbuffer at DetailActivityStringBuffer
videoStringBuffer = new StringBuffer();
for(PostModel.VidCast vidCast : postModel.getvideoIDList()) {
videoStringBuffer.append(vidCast.getName());
String videoID = vidCast.toString();
}
But now I'm getting the videoID with the array brackets like that ["F3lyzrt"] I want it as a string to be only F3lyzrt, so I can pass it to my youtube player. Any advice will be appropriated.
Thanks,
It would look something like this:
JSONObject root = // however you get your root JSON object
JSONArray posts = root.optJSONArray("posts");
for(int i=0; i < posts.length(); i++){
JSONObject post = posts.optJSONObject(i);
int id = post.optInt("id");
JSONArray categories = post.optJSONArray("categories");
// etc.
}
Though you might want to consider using GSON or Jackson. With those libraries you can define a model to represent the data (jsonschema2pojo.org can help with that) and then it does all the parsing for you.
EDIT
You're not even trying to get the video id. Here's your code:
for (int s = 0; s < finalObject.getJSONArray("videoID").length(); s++){
{
postModel.setVideoID(videoID);
postModelList.add(postModel);
}
You see how you're not retrieving the contents of the json array?
JSONArray videoIds = finalObject.getJSONArray("videoID");
for (int s = 0; s < videoIds.length(); s++){
String videoID = videoIds.optString(s);
postModel.setVideoID(videoID);
postModelList.add(postModel);
}
I have a JSON String structured in the following way and it throws an exception passing it into JSONArray timeJSONArray = new JSONArray(time);
This is the error Value [{"daysByte":158,"from":1020,"to":1260},{"daysByte":96,"from":1020,"to":1320}] at 0 of type org.json.JSONArray cannot be converted to JSONObject This is how I receive the array and I can't change it, so I'm having trouble converting it to a JSON Object instead of a JSON String which is the format it's currently in. What am I doing wrong?
[
[
{
"daysByte":30,
"from":660,
"to":1290
},
{
"daysByte":96,
"from":660,
"to":1320
},
{
"daysByte":128,
"from":1050,
"to":1290
}
],
[
{
"daysByte":252,
"from":690,
"to":840
},
{
"daysByte":252,
"from":1050,
"to":1260
}
]
]
This is the code I am working with. I'm getting the value passed in as a string
public ArrayList<String> getTimeList(String time){
System.out.println("PLACES ACTIVITY " + time);
ArrayList<String> times = new ArrayList<>();
try{
//JSONObject timeJSONObject = new JSONObject(time);
JSONArray timeJSONArray = new JSONArray(time);
ArrayList<LegacyTimeSpan> timeSpanList = new ArrayList<>();
LegacyTimeSpanConverterImpl converter = new LegacyTimeSpanConverterImpl();
for(int i = 0; i < timeJSONArray.length(); i++){
int daysByte = timeJSONArray.getJSONObject(i).getInt("daysByte");
int from = timeJSONArray.getJSONObject(i).getInt("from");
int to = timeJSONArray.getJSONObject(i).getInt("to");
System.out.println("TO " + to);
LegacyTimeSpan timeSpan = new LegacyTimeSpan(daysByte, from, to);
timeSpanList.add(timeSpan);
}
Log.d("Time span list", timeSpanList.toString());
WeekSpan weekSpan = converter.convertToWeekSpan(timeSpanList);
List<DayTimeSpanPair> dayTimeSpanPair = weekSpan.toDayTimeSpanPairs();
for(int i = 0; i< dayTimeSpanPair.size(); i++){
String timeRange = buildTimeString(dayTimeSpanPair.get(i));
times.add(timeRange);
}
} catch(JSONException e){
Log.d("PLACES EXCEPTION JSON",e.getMessage());
}
return times;
}
This Code should work i think as u declare the json Format.
[
[
{
} ,{},{} // Json Object Structure as u defined in you Question
topArray = ],
[
{
},{},{}
]
]
for(JSONArray objArray : topArray){
for(JSONObject eachObject : objArray){
System.out.println(eachObject.get("daysByte"););
System.out.println(eachObject.get("from");
System.out.println(eachObject.get("to");
}
}
Hi following code is working for your json I have tried. It is specific for your json not generic. so if you want you can use it.
try{
JSONArray jsonArray = new JSONArray(data); //insted "Data" pass your json Strint
for(int i=0 ; i<jsonArray.length() ; i++){
JSONArray internalArray = jsonArray.getJSONArray(i);
for(int j = 0 ; j < internalArray.length() ; j++){
JSONObject internalObject = internalArray.getJSONObject(j);
Log.d("data" , internalObject.getString("daysByte"));
Log.d("data" , internalObject.getString("from"));
Log.d("data" , internalObject.getString("to"));
}
}
}catch(Exception e){
Log.d("data" ,"Error");
}
}
You have two arrays, one array within other.
You have to do like this:
for(JSONArray temp: timeJsonArray)
{
// try to convert to json object
}
It is a 2D Array.
System.out.println("days");
String content = new Scanner(new File("C:/day.txt")).useDelimiter("\\Z").next();
Day[][] customDayWrap = new Gson().fromJson(content, Day[][].class);
for (Day[] days : customDayWrap) {
for (Day day : days) {
System.out.println(day.getDaysByte());
System.out.println(day.getFrom());
System.out.println(day.getTo());
}
}
And your Day Class will be something like this.
public class Day {
#SerializedName("daysByte")
#Expose
private Integer daysByte;
#SerializedName("from")
#Expose
private Integer from;
#SerializedName("to")
#Expose
private Integer to;
/**
*
* #return
* The daysByte
*/
public Integer getDaysByte() {
return daysByte;
}
/**
*
* #param daysByte
* The daysByte
*/
public void setDaysByte(Integer daysByte) {
this.daysByte = daysByte;
}
/**
*
* #return
* The from
*/
public Integer getFrom() {
return from;
}
/**
*
* #param from
* The from
*/
public void setFrom(Integer from) {
this.from = from;
}
/**
*
* #return
* The to
*/
public Integer getTo() {
return to;
}
/**
*
* #param to
* The to
*/
public void setTo(Integer to) {
this.to = to;
}
}
I tested this (I am using Google GSON library), and I was able to successfully read it.
Basically, there are two JSON arrays but you are accessing only one arrays that is why that error is shown
try {
JSONArray jsonArray = new JSONArray(a);
for (int j=0;j<jsonArray.length();j++) {
JSONArray timeJSONArray = jsonArray.getJSONArray(j);
for(int i = 0; i < timeJSONArray.length(); i++){
int daysByte = timeJSONArray.getJSONObject(i).getInt("daysByte");
int from = timeJSONArray.getJSONObject(i).getInt("from");
int to = timeJSONArray.getJSONObject(i).getInt("to");
System.out.println("TO " + to);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
After 1 hour of debugging your Json array I finally managed to figure out your actual issue. Its not only a Json Array its array inside the array.
So loop like this,
for (int i = 0; i < timeJSONArray.length(); i++) {
for(int j= 0;j<i;j++) {
int daysByte = timeJSONArray.getJSONArray(i).getJSONObject(j).getInt("daysByte");
int from = timeJSONArray.getJSONArray(i).getJSONObject(j).getInt("from");
int to = timeJSONArray.getJSONArray(i).getJSONObject(j).getInt("to");
Log.d("dataRecieved", "daybyte " + daysByte + "from " + from + "to " + to);
}
}
And do others as you need.
In my below code, colData stores JSON String. Sample example for colData-
{"lv":[{"v":{"price":70.0,"userId":419},"cn":3},
{"v":{"price":149.99,"userId":419},"cn":3},
{"v":{"price":54.95,"userId":419},"cn":3}],
"lmd":20130206212543}
Now I am trying to match id value with userId value in the above JSON String. I am getting id value from a different source.
Meaning if id value is 419 then in the above JSON String userId value should also be 419. And in the JSON String, it might be possible there are lot of userId values so all the userId values should be matching with id. If any of them doesn't matches then log the exception.
So I was trying something like this-
final int id = generateRandomId(random);
for (String str : colData) {
if (!isJSONValid(str, id)) {
// log the exception here
LOG.error("Invalid JSON String " +str+ "with id" +id);
}
}
public boolean isJSONValid(final String str, final int id) {
boolean valid = false;
try {
final JSONObject obj = new JSONObject(str);
final JSONArray geodata = obj.getJSONArray("lv");
final int n = geodata.length();
for (int i = 0; i < n; ++i) {
final JSONObject person = geodata.getJSONObject(i);
JSONObject menu = person.getJSONObject("v");
if(menu.getInt("userId") == id) {
valid = true;
}
}
} catch (JSONException ex) {
valid = false;
}
return valid;
}
As per my understanding it looks like I can make isJSONValid method more cleaner. In my above isJSONValid method as I am repeating some stuff which I shouldn't be doing. Can anyone help me out how to make this more cleaner if I have missed anything. I will be able to learn some more stuff. Thanks for the help
You can initialize valid = true and set it to false when you find a non-valid userId and immediately fail:
public boolean isJSONValid(final String str, final int id) {
boolean valid = true;
try {
final JSONObject obj = new JSONObject(str);
final JSONArray geodata = obj.getJSONArray("lv");
final int n = geodata.length();
for (int i = 0; i < n; ++i) {
final JSONObject person = geodata.getJSONObject(i);
JSONObject menu = person.getJSONObject("v");
if(menu.getInt("userId") != id) {
valid = false;
break;
}
}
} catch (JSONException ex) {
valid = false;
}
return valid;
}
This way you iterate through all array's elements only if all are valid, which is the only case you actually have to.