How to loop trough nested JSON and get value using Java, SpringBoot - java

I have a nested JSON that I want to loop through and get value based on key.
Data.json
{
"car": [
{
"date": 1324599600000,
"values": [
{
"name": "Audi",
"price": "11212.12"
},
{
"name": "Bmw",
"price": "22321.3"
},
{
"name": "Cittroen",
"price": "23432.2"
},
{
"name": "Tuareg",
"price": "556456.3"
}
]
}
I created 3 object models based on JSON data.
CarResponse.java
public class CarResponse {
#JsonProperty(value = "car")
List<Car> cars;
//getters,setters
Car.java
public class Car{
#JsonProperty("values")
private List<CarValue> carValue;
//getters, setters
CarValue.java
public class CarValue {
private String name;
private BigDecimal price;
//getters, setters
DataParse.java
public class DataParse{
CarResponse response;
public CarValue parse(){
CarValue carValue = new CarValue();
//NEED HELP WITH THIS PART
for(Car cars : response.getQuote()){
for(CarValue qv : cars.getCarValue()){
String type = qv.get("name").asText();
Decimal value = qv.get("price").decimalValue();
carValue.setName(qv.getName());
carValue.setPrice(qv.getPrice());
}
}
return quoteValue;
}
}
In JSON I need to check if car name is Audi and if car name is Tuareg then save it and display it.
Nested for loop part of code is not working
for(Car cars : response.getQuote()){
for(CarValue qv : cars.getCarValue()){
String type = qv.get("name").asText();
Decimal value = qv.get("price").decimalValue();
carValue.setName(qv.getName());
carValue.setPrice(qv.getPrice());
}
}
Just put it as an example of what I need to do in this step which is check for key in JSON and if it is that key with for example name = Audi then
carValue.setName(qv.getName());
With my code above I am getting this in the console.
carValue=[carValue{name=null, price=null}

Assuming that your deserialization is working correctly, you should change the part that "is not working" to:
String type = qv.getName();
BigDecimal value = qv.getPrice();
If for some reason you want to use this qv.get(key) method, you should post its implementation.
When getName and getPrice are still returning null, it means you have a problem with the deserialization, for example a wrong setter method name. Still, without the implementation is impossible to understand.
Here is the official documentation of Jackson, the library used by default with spring-boot for JSON serialization / deserialization.
And here is Spring blog post about it.

Related

How to load json data in java?

I'm quite new to API testing, I am wondering how to best and simple load some body?
I created simple pojo classes, but i am having problems with nested json.
ex:
{
"listOfItems": [
{
"name": "name1",
"value": "Jack"
},
{
"name": "nameDate",
"value": "20-08-2021-08-00-00"
},
{
"name": "address",
"value": "address here",
}
{
"name": "name2",
"value": "Smith"
}
],
"something": [],
"size": 1
}
Then, in classes I used:
ClassName {
private List<ListOfItems> listOfItems;
private List<something> something;
private int size;
//setters and getters
}
and
Class ListOfItems{
private String name;
private String value;
//getters and setters
}
then in test class I am trying to use it, but have no idea how.
public Class Test {
ClassName className = new ClassName();
ListOfItems list = new ListOfItems();
//how to get list with 3x name and 3x value like in json?
className.setsize(150);
given().when().body(???).post("\endpoint").then()...
}
But I have no idea how to declare those 4 properties (name, value)
You are actually on a pretty good track, you can use Gson library to help you out, Here is the video example for your explanation which I used to learn Gson back when I needed it

Deserialization with JSON objects which fields can be of different types

I have the following json file:
{
"authors":
[{"id":"author7",
"book":[
[
{
"value":{"pages":123}}]]},
{
"id": "author3",
"book": [
[
{
"value": {
"title": "LOTR"
}
},
{
"value": {
"boolean": false
}
},
],
[
{
"value": {
"pages": 350
}
},
{
"value": {
"boolean": false
}
},
],
[
{
"value": {
"boolean": false
}
},
{
"value": {
"pages": 150
}
},
]
]
},
}
I want to be able to create an object of Author but I am having problems while mapping the Json file with the Java classes I have created.
I understand that, while mapping the json file with the java classes, Authors class should have as fields
public class Authors{
private String authorId;
private Book book;
}
Class Book should be like this
public class Book {
private List<Values> values
public Book() {
}
}
But what about class Values?
public class Values{
private int pages;
private Boolean bool;
private String title;
public Values() {
}
}
Is this the correct way to map it? Because I see that if I create an object of Values it will ask me to modify the constructor or create a new constructor for each different object that comes from Json
Thank you for reading and helping!
Easy way out would to be to define Values by type 'object' as,
public class Book {
private List<Object> values
}
This way you won't run into the issue of having properties with null values when they don't exist in the JSON. Also, the JSON would be entirely parsed into an object even if new properties are get introduced (or which may not be defined under values class, as you have done above causing those not being mapped to the object).
However, when you are using 'object', be mindful with your logic that uses this parsed object. Although, you are assured to access the properties from the object as in the JSON, you will have to conditionally check whether the nessacary property exists first in each logical context to avoid possible undefined value errors.

Json Deserialize for hetero-type json Java

Apologies in advance, I'm a little new to JSON parsing and I m facing a problem in parsing JSON in Object in java.
{ result: {
"City": {
"Delhi": {
"A-Hospital": {
"pincode": 400001
},
"B-Hospital": {
"pincode": 400002
},
"C-Hospital": {
"pincode": 400003
},
.
.
.
},
"Mumbai": {
"A-Hospital": {
"pincode": 500001
},
"B-Hospital": {
"pincode": 500002
},
"C-Hospital": {
"pincode": 500003
},
.
.
.
},
"Bangalore": {
"A-Hospital": {
"pincode": 600001
},
"B-Hospital": {
"pincode": 600002
},
"C-Hospital": {
"pincode": 600003
},
"D-Hospital": {
"pincode": 600004
},
.
.
.
}
}
}
}
Receiving Json is received from 3rd person hence can't the format.
How to create the class structure for such dynamic json and parse into Object ?
class City{
private Map<String, Map<String,Hospital>> hours;
//Getter and Setter
}
class Hospital {
private String pincode;
//Getter and Setter
}
I want to form a Map of the City with Hospital(A-Hospital,B-Hospital,etc) as Object. Example: Map<String,Hospital> cityHospitalMapping. class Hospital { String HospitalName; Integer pincode; }
But How to write the Deserializer ?
Tried
JsonObject allcities = (JsonObject) json.get("result");
City cities = new Gson().fromJson(allcities,City.class);
But cities is not containing any data.
Result:
cities{pincode=null}
Edited because you added the result in your JSON. Your problem here - after edit - is that City you declared does not contain but it itself IS a Map<String, Map<String,Hospital>>.
First of all you need a "wrapper" class, say Data. That is because your JSON example has an object that contains Response that contains City.
For City, there are no fixed field names so you need to deserialize it as a Map.
The same applies to values held in the map City. Values in City are also type of Map let us call these values inner map. Because there is this one fixed field name pincode you can declare before mentioned values in this inner map as of type Hospital, leading to a class like:
#Getter #Setter
public class Data {
#Getter #Setter
public class Result {
private Map<String, Map<String, Hospital>> City;
#Getter #Setter
public class Hospital {
private String pincode;
}
}
private Result result;
}
Now if you deserialize with Gson using this above class you can use it like:
Data data = gson.fromJson(JSON, Data.class);
Map<String, Map<String, Hospital>> city = data.getResult().getCity();
and obtain 400002.
You could implement some more or less complex custom deserializer but maybe it is more easy to deserialize JSON as it is and after tath do some mappings to other types of classes if needed.

How to map Json to Java object using jackson

I am using jackson to map json which I get from my post rest api to map to a java object.
the json is represent by
{
"baseName": "xyz",
"salary": [
{
"id": 1,
"info": {
"ename": "john",
"eid": 143
}
},
{
"id": 2,
"info": {
"ename": "bg",
"eid": 123
}
}
]
}
The java class are represent by
BaseInfo.java
class BaseInfo {
String baseName;
ArrayList<salary> salaries = new ArrayList<salary>();
}
Salary.java
class Salary {
int id;
EmplInfo emp;
}
EmplInfo.java
class EmplInfo{
String ename;
int eid;
}
But in the when call the api with this json I get the arraylist initialized but contains nothings. What I am doing wrong ? I get other information like baseName,etc
You can use the JsonProperty annotation to rename properties
class BaseInfo {
String baseName;
#JsonProperty("salary")
ArrayList<salary> salaries = new ArrayList<salary>();
}
class Salary {
int id;
#JsonProperty("info")
EmplInfo emp;
}
Following are the solutions:
Either add JsonProperty annotations as specified by Michael or update json keys i.e 'salary' to 'salaries' and 'info' to 'emp'

How to Parse Nested / Multiple Json Objects using Retrofit

The JSON I'm parsing looks like this:
{ "version": 1
"data": {
"1001": {
"id": 1001,
"name": "herp",
"into": [
"3111": "we"
]
},
"1032": {
"id": 1002,
"name": "derp",
"into": [
"36": "w",
"12341: "c"
],
"tags": [
"hi there"
],
"cost" {
"even": 15
}
},
"1603": {
"id": 1003,
"name": "her",
"into": [
"37": "dll",
"58": "eow",
"32145": "3a"
],
"cost" {
"highest": 325
"lowest": 100
}
},
.... Even more data
}
The Json that is within "data" goes on for a while and does not have a set endpoint. I have no control over the Json, I'm just trying to read it. Unfortunately, with my class code I'm unable to get it to work. When I make a retrofit call the information inside "data" is empty.
I've tried many iterations of implementing this, including using a deserializer and restructuring my POJO code. This is the current state of my Data class:
public class Data {
private Map<String, Item> itemData;
// Relevant Getters, Setters and Constructors //
}
For my Item Class, the main issue is that the JSON Content isn't set, it can vary at times. As you can see above the values inside "into" vary and sometimes the amount of things within item changes as well such as "tags" or "cost":
public class Item {
private int id;
private String name;
private String group;
private String description;
private Map<String, String> into;
private List<String> tags;
private Map<String, Integer> cost;
// Relevant Getters, Setters and Constructors //
When I use this code my data class is empty, I don't see any errors in the log so I can't seem to figure out why the GSON isn't working with this.
In case you wanted to see how I construct my RestClient, here it is:
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(ROOT)
.setClient(new OkClient(new OkHttpClient()))
.setLogLevel(RestAdapter.LogLevel.FULL);
RestAdapter restAdapter = builder.build();
REST_CLIENT = restAdapter.create(DataApi.class);
I know that my Rest Query works because I can get the content within "version" but everything inside data is null.
I am officially a dumb scrub and completely looked over the easiest possible fix and should have my account and developer title revoked.
This is all I should have done:
public class ItemGroup {
private String version;
private Map<String,Item> data;
//...Man i'm so dumb...
}
AS REFERENCE FOR THE FUTURE. The reason why this works is because the JSON is in this format { { } { } { } }. Which means you have 3 objects of objects, as opposed to { [ ] [ ] [ ] } which is 3 objects of a list. What I had done was treat { { } { } { } } as { { { } { } { } } }. Which is not correct. By using a map which is basically a collection of pairs, we are able to imitate the { { } { } { } } with a Map.
Map Object { {Key-Pair Object} {Key-Pair Object} {Key-Pair Object} }
Just a quick idea for your Pojos:
Not sure if this will work. Maybe write a custom deserializer.
public class YourResponse {
int version;
Data data;
class Data {
Subdata subData;
}
class Subdata {
private int id;
private String name;
private ArrayList<Into> into;
private ArrayList<String> tags;
//...
}
class Into {
// "3111": "we"
private String into;
}
}

Categories

Resources