How to parse JSON response which contains nested JSON array - arrays

I'm trying to parse a JSON response from an API and store the data to DATA CLASS and sending the data to recycler adapter as ArrayList.
The JSON Array has another array of objects inside, and I'm not able to find a way to properly parse that JSON response.
Here is my data class:
data class OrderDetails (
val orderId: String, // order_id value from json object goes here //
val restaurantName: String, // restaurant_name value from json object goes here //
val totalCost: String, // total_cost value from json object goes here //
val orderDate: String, // order_placed_at value from json object goes here //
val orderFoodDetails: String // food_items value in json response is an array and i'm stuck here //
)
Here is my Kotlin code:
try {
val data = it.getJSONObject("data")
val success = data.getBoolean("success")
if (success) {
val arrayData = data.getJSONArray("data")
for (i in 0 until arrayData.length()) {
val orderJsonObject = arrayData.getJSONObject(i)
val orderObject = OrderDetails(
orderJsonObject.getString("order_id"),
orderJsonObject.getString("restaurant_name"),
orderJsonObject.getString("total_cost"),
orderJsonObject.getString("order_placed_at"),
orderJsonObject.getJSONArray("food_items").toString() // getting array and storing as a string
)
orderList.add(orderObject)
for (orders in orderList) {
val foodData = orders.orderFoodDetails
val jsonFood = JSONArray(foodData)
for (j in 0 until jsonFood.length()) {
val foodJsonObject = jsonFood.getJSONObject(j)
val foodObject = OrderFoodDetails(
foodJsonObject.getString("food_item_id"),
foodJsonObject.getString("name"),
foodJsonObject.getString("cost")
)
ordersFood.add(foodObject)
}
}
}
Here is the Json response:
{
"data": {
"success": true,
"data": [
{
"order_id": "17790",
"restaurant_name": "Rotten Tomatoes",
"total_cost": "280",
"order_placed_at": "02-11-20 19:00:54",
"food_items": [
{
"food_item_id": "156",
"name": "Rotten Bhajiya",
"cost": "100"
},
{
"food_item_id": "155",
"name": "Rotten Salad",
"cost": "100"
},
{
"food_item_id": "154",
"name": "Rotten Soup",
"cost": "80"
}
]
},
Required Output
Prefered Output
My output
my current output

do you tried to use GSON or Moshy lib ?
This case will be easier solved with one of this :)
If you don't want to use one of them, just try to replace your for cycle to map or for each, to make it more readable. Looks like you make it right, but can you check the result of try catch block please?

Related

Kotlin Gson parsing Json Object and Array

I am pretty new to Kotlin and Json and on my work I use GSON to parse the Json.
I need to parse the following Json file into a Class by using GSON.
{
"apiKey": "blablabla",
"baseUrl": "blablabla",
"requestData": [
{
"lng": "6.971",
"lat": "50.942",
"rad": "1.5",
"type": [
"diesel",
"super"
]
},
{
"lng": "6.442",
"lat": "51.180",
"rad": "1.5",
"type": [
"diesel",
"super"
]
},{
"lng": "7.136",
"lat": "50.991",
"rad": "1.5",
"type": [
"diesel",
"super"
]
}
]
}
Now I tried to make a data class like this:
data class ApiParameterData(
var apiKey: String? = null,
var baseUrl: String? = null,
var requestData: String? = null) {
}
I also made another class to store the Json informations in it like this:
class Tankstelle: JsonDeserializer<ApiParameterData> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?
): ApiParameterData {
json as JsonObject
val apiKey = json.get("apiKey").asString
val baseUrl = json.get("baseUrl").asString
val requestDataJson = json.get("requestData")
val requestData = if (requestDataJson.isJsonObject) requestDataJson.asJsonObject.toString() else requestDataJson.toString()
return ApiParameterData(apiKey, baseUrl, requestData)
}
}
I tried to call it like that:
val gsonConfig = GsonBuilder().registerTypeAdapter(ApiParameterData::class.java, Tankstelle()).create()
val tanke = gsonConfig.fromJson(readJson, ApiParameterData::class.java)
println(tanke.requestData?.get(0))
But of course the output I get is "[" . I think because I get back a String or something and this is the first symbol of it?
I need to loop trough the requestData list and store it as a instance of a class and need to access each different value.
The thing is that I want to give the Json file different places and ranges it should look for gasstations. By reading the Json it should take all the pieces and create a link for each place I write in the requestData list. So in this case I would need 3 different links at the end. But this is another part I can do myself. I just don't know how to parse it so I can access and store every value in this Json.
Thank you already and have a great weekend!
If you need more informations just let me know
First you need to define two types that map to your JSON structure
class ApiParameterData(
val apiKey: String,
val baseUrl: String,
val requestData: List<RequestObject>
)
class RequestObject(
val lng: String,
val lat: String,
val rad: String,
val type: List<String>
)
Now simply parse it as
val apiData = Gson().fromJson(readJson, ApiParameterData::class.java) // No need to add TypeAdapter
// To get requestData
val requestData = apiData.requestData
requestData.forEach {
print("${it.lng}, ${it.lat}, ${it.rad}, ${it.type})
}

Converting a typescript class object with dictionary to a JSON array

After some digging I decided my backend needed to consume duplicate keys and as a consequence my frontend can no longer send a dictionary as a JSON string.
See my previous question.
After applying the solution provided
let mediatagRequest = new MediaTagRequest(tags);
const headers = { 'content-type': 'application/json' }
let jsonObject = {};
for (let entry of mediatagRequest.tags.entries())
{
jsonObject[entry[0]] = entry[1];
}
const body = JSON.stringify({
tags: jsonObject
});
My current output (which is what I then wanted)
{
"tags": {
"city": "Karachi"
}
However my needs have changed and after a bit of of struggle I couldn't get my desired output to be like this
{
"tags": [
{
"key": "city",
"value": "Karachi"
},
{
"key": "city",
"value": "Mumbai"
}
]
}
Could someone help, thank you.
To get your desired output you could use the Object.entries() function to get the key, value pairs separately. This code segment will turn an object into a list of objects with key value pairs:
test_object = {
karachi: "dubai",
mumbao: "moscow",
};
output = Object.entries(test_object).map(([key, value]) => ({ key, value}));
console.log(output);
You can adapt this code to select the desired parts of your object and format them as you like. There are other Object functions you can see in the documentation.

Karate: Can I iterate on a Json array response and do some conditional statements

My json array response is something like below:
response = [
{
"ID": "123",
"Name":"Test1",
"Data":{
"Status":"Red",
"Message":"user not valid",
"Code": "ERROR-P1"
}
},
{
"ID": "143",
"Name":"Test2",
"Data":{
"Status":"Amber",
"Message":"user data missing",
"Code": "ERROR-P2"
}
},
{
"ID": "133",
"Name":"Test3",
"Data":{
"Status":"Green",
"Message":"",
"Code": ""
}
}
There could be more entries in the json array with same data and status.
My use case is to check, based on a condition that if my json array has Status as Red or Amber, then message and code is not empty and similarly if my status is Green then message and code is empty.
I need to iterate to the entire array and validate this scenario.
And also need to get a count of Status: Red, Amber and Greens from the Array Json response.
What could be the best possible solution with karate?
Any help would be appreciated.
Thank you
Here you go:
* def red = []
* def amber = []
* def green = []
* def fun =
"""
function(x){
if (x.Data.Status == 'Red') karate.appendTo(red, x);
if (x.Data.Status == 'Amber') karate.appendTo(amber, x);
if (x.Data.Status == 'Green') karate.appendTo(green, x);
}
"""
* karate.forEach(response, fun)
* assert red.length == 1
* match each red..Message == 'user not valid'
* match each amber contains { Data: { Status: 'Amber', Message: 'user data missing', Code: 'ERROR-P2' } }

Processing error message 'The function getJSONArray(JSONArray) does not exist'

i am not sure why i am getting the error message 'The function getJSONArray(JSONArray) does not exist' when i run this sketch that uses a json query to Weather Underground. That comment seems illogical since Processing is recognising the id ref for the JSONArray.
The .json can be read here: http://api.wunderground.com/api/97a2805510de59e9/hourly/q/pws:IENGLAND274.json
Any thoughts? Thanks.
import com.francisli.processing.http.*;
HttpClient client;
String data;
com.francisli.processing.http.JSONObject weatherInfo;
JSONArray hourly_forecast;
int last = 0;
PImage img;
Float humidity = 50.2;
void setup() {
size(700, 700);
client = new HttpClient(this, "api.wunderground.com");
client.GET("/api/97a2805510de59e9/hourly/q/pws:IENGLAND274.json");
background(255);
}
void responseReceived(HttpRequest request, HttpResponse response) {
println(response.getContentAsString());
weatherInfo = response.getContentAsJSONObject();
JSONArray hourly_forecast = weatherInfo.getJSONArray(hourly_forecast);
}
There is no method called getJSONArray() that takes in a JSONArray as an argument.
The function should be used as JSONArray.getJSONArray(0) which gets the first array of elements in your JSON data. You can put this in a loop to get all of them.
Example (taken from: http://art.buffalo.edu/coursenotes/art380/reference/JSONArray_getJSONArray_.html):
// The following short JSON file called "data.json" is parsed
// in the code below. It must be in the project's "data" folder.
//
// [
// [
// { "name": "apple", "isFruit": true },
// { "name": "grape", "isFruit": true },
// { "name": "carrot", "isFruit": false }
// ],
// [
// { "name": "lettuce", "isFruit": false },
// { "name": "plum", "isFruit": true },
// { "name": "cinnamon", "isFruit": false }
// ]
// ]
JSONArray json;
void setup() {
json = loadJSONArray("data.json");
// Get the first array of elements
JSONArray values = json.getJSONArray(0);
for (int i = 0; i < values.size(); i++) {
JSONObject item = values.getJSONObject(i);
String name = item.getString("name");
boolean isFruit = item.getBoolean("isFruit");
println(name + ", " + isFruit);
}
}
// Sketch prints:
// apple, true
// grape, true
// carrot, false
Second problem with your code is that you're declaring hourly_forecast twice: once globally and once within the responseReceived() function. You probably want to remove JSONArray from hourly_forecast within the responseReceived() function.

how to copy the json response into an array in extjs?

I have a json response coming in from a php file, the json response looks as below results:
[
{
"header": "Client ID",
"dataindex": "clientID"
},
{
"header": "Client Name",
"dataindex": "clientName"
},
{
"header": "Progress Bar",
"dataindex": "progressBar"
}
]
Now I want to copy this data into an array in the following way
var allColumns = [];
//loop through the json response
var singleColumn = [];
singleColumn['header'] = Client ID from the json response whose key is header
singleColumn[dataindex'] = clientID from the json response whose key is header.
Please note: I need to do this is extjs3.
If I am getting you correctly you are getting the JSON as a string from an ajax call to your PHP handler in a string format and you want to cast it into a Javascript array of coloumn objects.
you can do it like this:
var allColumns = Ext.decode(YOUR PHP JSON FORMATTED RESULT);
this will allow you to iterate over the result set as an in memory javascript array of objects like this:
for(var i=0 ; i < allColumns.length; i++){
allColumns[i].header ...
allColumns[i].dataindex ...
}
I hope I got you right...

Resources