I am trying to construct a bit complex nested JSON for a POST request in my Android application, I am using Retrofit2 and GSON converter.
After constructing, I used GSON to print it out in order to be sure of what will be sent to the API endpoint. Below is the output I got
{
"agent_id":"testy",
"answer":[
{
"answer":"Yes",
"question_id":"1"
},
{
"answer":"Yes",
"question_id":"5"
},
{
"answer":"No",
"question_id":"6"
},
{
"answer":"No",
"question_id":"7"
},
{
"sub_question":[
{"sub_question_id":"2"},
{"sub_question_id":"2"},
{"sub_question_id":"2"},
{
"sub_answer":[
{"coord":"6.4378537,3.4289744000000155","text":""},
{"coord":"6.4378537,3.4289744000000155","text":""},
{"coord":"6.4378537,3.4289744000000155","text":""}
]
}
]
}
],
"street_id":3,
"token":"afadfadfadfdfHFGD_JSDHD"
}
However, the actual format I need is as seen below
{
"agent_id":"testy",
"answer":[
{
"answer":"Yes",
"question_id":"1",
"sub_question":[
{
"sub_question_id":"2",
"sub_answer":[
{"coord":"6.4378537,3.4289744000000155","text":""}
]
}
]
},
{
"answer":"No",
"question_id":"5",
"sub_question":[
{
"sub_question_id":"2",
"sub_answer":[
{"coord":"6.4378537,3.4289744000000155","text":""}
]
}
]
},
{
"answer":"Yes",
"question_id":"6",
"sub_question":[
{
"sub_question_id":"2",
"sub_answer":[
{"coord":"6.4378537,3.4289744000000155","text":""}
]
}
]
},
{
"answer":"No",
"question_id":"7",
"sub_question":[
{
"sub_question_id":"2",
"sub_answer":[
{"coord":"6.4378537,3.4289744000000155","text":""}
]
}
]
}
],
"street_id":3,
"token":"asdfasdfasdf3453adfafdaADN"
}
The code that does the construction is below
private void submitAnswers() {
List<Answer> answerList = new ArrayList<>();
List<SubQuestion> subQuestionList = new ArrayList<>();
List<SubAnswer> subQuestionAnswerList = new ArrayList<>();
//Adding QuestionID and QuestionAnswer to the Answer array
for (int k = 0; k < questSize.size(); k++) {
Answer answer1 = new Answer();
answer1.setQuestion_id(mainQuestAnsID.get(k));
answer1.setAnswer(mainQuestAns.get(k));
answerList.add(answer1);
}
for (int j = 0; j < subQuestID.size(); j++) {
SubQuestion subQuest = new SubQuestion();
subQuest.setSub_question_id(subQuestID.get(j));
subQuestionList.add(subQuest);
}
for (int h = 0; h < subQuestAns.size(); h++) {
SubAnswer subQuestionAnswer = new SubAnswer();
subQuestionAnswer.setText(subQuestAns.get(h));
subQuestionAnswer.setCoord("6.4378537,3.4289744000000155");
subQuestionAnswerList.add(subQuestionAnswer);
}
Answer answer = new Answer();
answer.setSub_question(subQuestionList);
answerList.add(answer);
SubQuestion subQuest = new SubQuestion();
subQuest.setSub_answer(subQuestionAnswerList);
subQuestionList.add(subQuest);
AnswerRequest answerRequest = new AnswerRequest();
answerRequest.setAgent_id(agentID);
answerRequest.setToken(token);
answerRequest.setStreet_id(streetID);
answerRequest.setAnswer(answerList);
//Gson for printing out the JSON
Gson gson = new Gson();
Type type = new TypeToken<AnswerRequest>() {
}.getType();
String json = gson.toJson(answerRequest, type);
System.out.println(json);
}
Can anyone tell what is wrong that makes me not to get the desired output?
I guess the main reason is that you are building your lists separately, while you should do it once for every answer.
For what I understand from your expected output, you have:
1 main object that has some parameters and a list of answer
each answer has some parameters and a list of subquestion
each subquestion has some parameters and a list of subanswers
So you should build your object in the same way. E.g. for each new answer, construct its list of subquestion, for each subquestion construct its list of subanswer
Code speaking it would be something like this:
for (int k = 0; k < questSize.size(); k++) {
Answer answer1 = new Answer();
answer1.setQuestion_id(mainQuestAnsID.get(k));
answer1.setAnswer(mainQuestAns.get(k));
// now construct the subquestion list of that new answer
List<SubQuestion> subQuestions = new ArrayList<>();
for (int j = 0; j < subQuestID.size(); j++) { // change the loop to get only what you need for the current answer
SubQuestion subQuest = new SubQuestion();
// add all the subquestions related to the answer here
...
// Construct the subanswer of that new subquestion
List<SubAnswer> subAnswers = new ArrayList<>();
for (int h = 0; h < subQuestAns.size(); h++) { // adapt the loop to get the subanswers related to the current subquestion
SubAnswer subQuestionAnswer = new SubAnswer();
// get the infos needed for this subanswer
...
// add the new subanswer to the list
subAnswers.add(subQuestionAnswer);
}
// add the subanswer list to the subquestion
subQuest.setSub_answer(
// add the subquestion to the list
subQuestions.add(subQuest);
}
// then add the list to the answer
answer1.setSub_question(subQuestions);
// finally add the answer to the list
answerList.add(answer1);
}
// now you can create the AnswerRequest object like before
And you should have a result that looks more like what you need now :)
Related
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
ElasticSearch Version - 2.4.0
Logs:
java.lang.IllegalArgumentException: The number of object passed must be even but was [1]
at org.elasticsearch.action.index.IndexRequest.source(IndexRequest.java:451)
at org.elasticsearch.action.index.IndexRequestBuilder.setSource(IndexRequestBuilder.java:186)
at org.apache.kafka.connect.elasticsearchschema.ElasticsearchSinkTask.put(ElasticsearchSinkTask.java:138)
at org.apache.kafka.connect.runtime.WorkerSinkTask.deliverMessages(WorkerSinkTask.java:381)
at org.apache.kafka.connect.runtime.WorkerSinkTask.poll(WorkerSinkTask.java:227)
at org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:170)
at org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:142)
at org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:140)
Code:
// This method will put the SinkRecords which are sent in bulk to Elastic Search with proper index and type.
public void put(Collection<SinkRecord> sinkRecords) {
try {
// Gets a list of SinkRecord from Kafka broker.
List<SinkRecord> records = new ArrayList<SinkRecord>(sinkRecords);
for (int i = 0; i < records.size(); i++) {
BulkRequestBuilder bulkRequest = client.prepareBulk();
// Looping through the SinkRecords and the size should be less than bulksize.
for (int j = 0; j < bulkSize && i < records.size(); j++, i++) {
SinkRecord record = records.get(i);
// Index and type is hardcoded and record.value() contains the Json message.
bulkRequest.add(client.prepareIndex("operative1", "test").setSource(record.value()));
}
i--;
// Executing bulk requests.
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
}
} catch (Exception e) {
}
}
Input given is -> { "id1": "file", "value1": "File" }
Please help to solve this.
Final Code looks like this by passing Map.
// This method will put the SinkRecords which are sent in bulk to Elastic Search with proper index and type.
public void put(Collection<SinkRecord> sinkRecords) {
try {
ObjectMapper mapper = new ObjectMapper();
// Gets a list of SinkRecord from Kafka broker.
List<SinkRecord> records = new ArrayList<SinkRecord>(sinkRecords);
for (int i = 0; i < records.size(); i++) {
BulkRequestBuilder bulkRequest = client.prepareBulk();
// Looping through the SinkRecords and the size should be less than bulksize.
for (int j = 0; j < bulkSize && i < records.size(); j++, i++) {
SinkRecord record = records.get(i);
// Index and type is hardcoded and record.value() contains the Json message.
Map<String, Object> map = mapper.readValue((String) record.value(), new TypeReference<Map<String, Object>>() {
});
bulkRequest.add(client.prepareIndex("operative1", "test").setSource(map));
}
i--;
// Executing bulk requests.
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
}
} catch (Exception e) {
}
}
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.
I am porting an Android-only Game to libgdx. The world and level info is stored in a json file.
I used to do access the array with getJSONArray(id) like this:
public static WorldVO create(JSONObject worldObject) {
WorldVO worldVO = new WorldVO();
worldVO.id = worldObject.getInt("id");
worldVO.unlock = worldObject.getInt("stars_to_unlock");
worldObject.getChild("levels");
JSONArray levelJsonArray = worldObject.getJSONArray("levels");
int len = levelJsonArray.length();
worldVO.levelVOs = new LevelVO[len];
for (int i = 0; i < len; i++) {
worldVO.levelVOs[i] = LevelVO.create(levelJsonArray.getJSONObject(i));
}
...
which worked fine but I cannot find the correct way to loop through the "levels" child of the "worldObect" Json in libgdx when i use JsonValue instead of JSONObject.
Accessing the integer fields is not a problem but JsonValue does not have a getJSONArray. Any idea what to use? Thanks!
Based on this : http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/JsonValue.html
Try this :
public static WorldVO create(JsonValue worldObject)
{
WorldVO worldVO = new WorldVO();
worldVO.id = worldObject.getInt("id");
worldVO.unlock = worldObject.getInt("stars_to_unlock");
JsonValue levels = worldObject.get("levels");
int len = levels.size;
worldVO.levelVOs = new LevelVO[len];
for (int i = 0; i < len; i++)
{
worldVO.levelVOs[i] = LevelVO.create(levels.get(i));
}