how to get all values of a key from a nested json - java

for example I have a json object like this:
{
"pic":"1.jpg",
"products":[
{
"id":1,
"pic":"4.jpg"
}
]
}
now I want to fetch all pic key inside an array or a list.
the result must be: ["1.jpg","4.jpg"]

There is a simple solution for this in jackson library.
String value = "{\"pic\":\"1.jpg\",\"products\":[{\"id\":1,\"pic\":\"4.jpg\"}]}";
JsonNode jsonNode = new ObjectMapper().readTree(value);
System.out.println(jsonNode.findValuesAsText("pic"));
You can add jackson by using following maven dependency.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
You can also pass file, inputstream to readTree().

Please try this code:
//define a list which will contain pic names
List<String> picList = new ArrayList<>();
try {
//jsonMap: your json object variable name
String picName = (String) jsonMap.get("pic");
picList.add(picName);
List<Map<String, Object>> products = (List<Map<String, Object>>) jsonMap.get("products");
for (Map<String, Object> product : products) {
String pic = (String) product.get("pic");
picList.add(pic);
}
System.out.println("=====List of pics===="+picList);
} catch (Exception e) {
}

It would be better if you parse the json to a POJO class. You can use Gson to convert json string to below Data class object.
String jsonString = "you json string here"
Data object = Gson().fromJson(jsonString, Data.class)
Now you have the object and can get product list from which you can iterate and get "pic" values.
Below is the class
package com.example;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Data {
#SerializedName("pic")
#Expose
private String pic;
#SerializedName("products")
#Expose
private List<Product> products = null;
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
-----------------------------------com.example.Product.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Product {
#SerializedName("id")
#Expose
private int id;
#SerializedName("pic")
#Expose
private String pic;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
}

If you want the list of pics within the products node, then you can get the entire JSON into a JSONObject, and iterate over the inner JSONArray
String str = "{\n" +
"\"pic\":\"1.jpg\",\n" +
"\"products\":[\n" +
"{\n" +
"\"id\":1,\n" +
"\"pic\":\"4.jpg\"\n" +
"}\n" +
"]\n" +
"\n" +
"}";
ArrayList<String> list = new ArrayList<>();
try {
JSONObject root = new JSONObject(str);
JSONArray products = root.getJSONArray("products");
for (int i = 0; i <= products.length(); i++) {
String value = ((JSONObject) products.get(i)).getString("pic");
list.add(value);
}
} catch (JSONException e) {
e.printStackTrace();
}
Log.d(TAG, "onCreate: " + list);

Related

How to compare Json Arrays having elements not in same order

I have 2 API responses and converted them into Json Array. When I convert 2 jsons into a map of key value pair the order of values are different and unable to perform comparison between 2 API responses.
JsonArray from API 1:
[
{
"employeeSalutation": null,
"EmployeeName": "Example",
"EmployeeCode": "SAA",
"Zip": 12345,
"DepartmentName": "Social science",
"EmployeeAddress": "123 st",
"StateCode": 9,
"updatedDate": "2018-01-22T03:48:43.59",
"EmployeeId": 1257
}
]
Json Array from API 2:
[
{
"Emp_Name": "Example",
"emp_Sal": null,
"Dept_Name": "Social science",
"Emp_addr": "123 st",
"Zip": "12345",
"Stat_cd": 9,
"Emp_id": 1257,
"upd_d": "2018-01-22 03:48:43.59",
"Emp_Code": "SAA"
}
]
I converted 2 Json Arrays into map of key-value pair with EmployeeId as key in Array 1 and Emp_id as key in Array 2. When I compare 2 maps the order of values in map are different and getting failed.
How to compare 2 APIs to ensure the values of each element in 2 apis are matched.
First of all you need to create a model which will represent these two JSON payloads. They are almost similar except of key names and values for Zip key where in first payload it is a number primitive in second - String primitive. Dates also have different format so you need to handle them by implementing custom date deserialiser.
Definitely you should use Jackson or Gson library which allows to deserialise JSON to POJO model, provide custom date deserialisers, any many other features.
Below example provide example solution:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonApi1 = new File("./resource/test.json").getAbsoluteFile();
File jsonApi2 = new File("./resource/test1.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
private final SimpleDateFormat formatWithTimeZoneIndicator = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SS");
private final SimpleDateFormat formatWithoutTimeZoneIndicator = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SS");
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String date = json.getAsString();
try {
return formatWithoutTimeZoneIndicator.parse(date);
} catch (ParseException e) {
try {
return formatWithTimeZoneIndicator.parse(date);
} catch (ParseException e1) {
throw new JsonParseException(e1);
}
}
}
})
.create();
Type employeesType = new TypeToken<List<Employee>>() {}.getType();
try (FileReader readerApi1 = new FileReader(jsonApi1);
FileReader readerApi2 = new FileReader(jsonApi2)) {
List<Employee> employees1 = gson.fromJson(readerApi1, employeesType);
List<Employee> employees2 = gson.fromJson(readerApi2, employeesType);
System.out.println(employees1);
System.out.println(employees2);
System.out.println(employees1.equals(employees2));
}
}
}
class Employee {
#SerializedName(value = "employeeSalutation", alternate = {"emp_Sal"})
private String employeeSalutation;
#SerializedName(value = "EmployeeName", alternate = {"Emp_Name"})
private String employeeName;
#SerializedName(value = "EmployeeCode", alternate = {"Emp_Code"})
private String employeeCode;
#SerializedName("Zip")
private JsonPrimitive zip;
#SerializedName(value = "DepartmentName", alternate = {"Dept_Name"})
private String departmentName;
#SerializedName(value = "EmployeeAddress", alternate = {"Emp_addr"})
private String employeeAddress;
#SerializedName(value = "StateCode", alternate = {"Stat_cd"})
private int stateCode;
#SerializedName(value = "updatedDate", alternate = {"upd_d"})
private Date updatedDate;
#SerializedName(value = "EmployeeId", alternate = {"Emp_id"})
private int employeeId;
public String getEmployeeSalutation() {
return employeeSalutation;
}
public void setEmployeeSalutation(String employeeSalutation) {
this.employeeSalutation = employeeSalutation;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeeCode() {
return employeeCode;
}
public void setEmployeeCode(String employeeCode) {
this.employeeCode = employeeCode;
}
public JsonPrimitive getZip() {
return zip;
}
public void setZip(JsonPrimitive zip) {
this.zip = zip;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getEmployeeAddress() {
return employeeAddress;
}
public void setEmployeeAddress(String employeeAddress) {
this.employeeAddress = employeeAddress;
}
public int getStateCode() {
return stateCode;
}
public void setStateCode(int stateCode) {
this.stateCode = stateCode;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return stateCode == employee.stateCode &&
employeeId == employee.employeeId &&
Objects.equals(employeeSalutation, employee.employeeSalutation) &&
Objects.equals(employeeName, employee.employeeName) &&
Objects.equals(employeeCode, employee.employeeCode) &&
Objects.equals(zip.getAsString(), employee.zip.getAsString()) &&
Objects.equals(departmentName, employee.departmentName) &&
Objects.equals(employeeAddress, employee.employeeAddress) &&
Objects.equals(updatedDate, employee.updatedDate);
}
#Override
public int hashCode() {
return Objects.hash(employeeSalutation, employeeName, employeeCode, zip, departmentName, employeeAddress, stateCode, updatedDate, employeeId);
}
#Override
public String toString() {
return "Employee{" +
"employeeSalutation='" + employeeSalutation + '\'' +
", employeeName='" + employeeName + '\'' +
", employeeCode='" + employeeCode + '\'' +
", zip=" + zip +
", departmentName='" + departmentName + '\'' +
", employeeAddress='" + employeeAddress + '\'' +
", stateCode=" + stateCode +
", updatedDate='" + updatedDate + '\'' +
", employeeId=" + employeeId +
'}';
}
}
Above code prints:
[Employee{employeeSalutation='null', employeeName='Example', employeeCode='SAA', zip=12345, departmentName='Social science', employeeAddress='123 st', stateCode=9, updatedDate='Mon Jan 22 03:48:43 CET 2018', employeeId=1257}]
[Employee{employeeSalutation='null', employeeName='Example', employeeCode='SAA', zip="12345", departmentName='Social science', employeeAddress='123 st', stateCode=9, updatedDate='Mon Jan 22 03:48:43 CET 2018', employeeId=1257}]
true
JSONAssert librairy is very handy for such tasks.
Here is good tutorial on how to use it.
I hope it helps you.
Since you are doing this in Java, I suggest you map this values into Java objects.
That way, it would be extremely easy for you to compare values. You can use libraries like Gson for that but here i will show you how to do that without a library.
Create a class which will be easy to use for your API responses:
public class Employee {
private String employeeSalutation; //i am not sure what type should this variable be
private String employeeName;
private String employeeCode;
private int zip;
private String departmentName;
private String employeeAddress;
private int stateCode;
private String updatedDate;
private int employeeId;
//this is where your parser can be used
public Employee(String employeeSalutation, String employeeName, String employeeCode,
int zip, String departmentName, String employeeAddress, int stateCode,String updatedDate, int employeeId){
this.employeeSalutation = employeeSalutation;
this.employeeName = employeeName;
this.employeeCode = employeeCode;
this.zip = zip;
this.departmentName = departmentName;
this.employeeAddress = employeeAddress;
this.stateCode = stateCode;
this.updatedDate = updatedDate;
this.employeeId = employeeId;
}
//getters, setters
}
Now you could have a class which will be used to convert this arrays into Java Objects, lets call it EmployeeConverter:
public class EmployeeConverter {
public Employee convertApi1Employee(String json){
//since you didn't clarify how are you accessing your Json values, i will now use pseudo-code to finish my answer.
//using variable.value pseudo-code to access json property value
return new Employee(employeeSalutation.value, EmployeeName.value, EmployeeCode.value, Zip.value, DepartmentName.value, EmployeeAddress.value, EmployeeAddress.value, StateCode.value, updatedDate.value, EmployeeId.value);
}
}
You should create method convertApi2Employee() which will have exact functionality as convertApi1Employee() method, but will use different JSON object.
I hope this helps.

Parse JSON String using ObjectMapper java API

I have a JSON as below. The goal is to get the corresponding "ip","PRODUCTTYPE" and "ID" values.
{
"customerId": "dummy1",
"nameIdmap": {
"10.2.1.0": "{PRODUCTTYPE=null, ID=123}",
"10.2.1.3": "{PRODUCTTYPE=null, ID=456}",
"10.2.1.4": "{PRODUCTTYPE=null, ID=789}",
"10.2.1.5": "{PRODUCTTYPE=null, ID=193}"
}
}
I am using the ObjectMapper API to parse and fetch the values.
ObjectMapper om = new ObjectMapper();
JsonNode node = om.readTree(stringToBeParsed);
String customerID = node.get("customerId").asText();
System.out.println("The Customer ID is ::: "+customerID);
JsonNode nameIdmap = node.get("nameIdmap");
StreamSupport.stream(nameIdmap.spliterator(), false).forEach(
kv -> {
System.out.println(kv.asText().split(",")[0] +" ,
"+kv.asText().split(",")[1]);
});
But the issue is I, am unable to get the key which is the ip-address in this case. Tried different ways to achieve but could not get what i want.
I checked if the nameIdmap is an array nameIdmap.isArray() but it is false.
I also tried below but could not get the ip i.e the key
JsonNode nameIdmap = node.get("nameIdmap");
StreamSupport.stream(nameIdmap.spliterator(), false).collect(Collectors.toList())
.forEach(item -> {
System.out.println(item.asText());
});;
You can try Custom Deserializer as below
1. Create Item class
This is a POJO which stands for an ID and a map of String and IPItem
public class SOItem {
#Override
public String toString() {
return "SOItem [id=" + id + ", map=" + map + "]";
}
String id;
Map<String, SOIPItem> map = new HashMap();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, SOIPItem> getMap() {
return map;
}
public void setMap(Map<String, SOIPItem> map) {
this.map = map;
}
}
2. Create IPItem class
This is a POJO for an ID and ProductType
public class SOIPItem {
private String type;
private String id;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public String toString() {
return "SOIPItem [type=" + type + ", id=" + id + "]";
}
public SOIPItem(String type, String id) {
super();
this.type = type;
this.id = id;
}
}
3. Create a Custom Deserializer
import java.io.IOException;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
public class SOCustDeser extends StdDeserializer<SOItem> {
public SOCustDeser() {
this(null);
}
public SOCustDeser(Class<?> vc) {
super(vc);
}
/**
*
*/
private static final long serialVersionUID = -394222274225082713L;
#Override
public SOItem deserialize(JsonParser parser, DeserializationContext arg1)
throws IOException, JsonProcessingException {
SOItem soItem = new SOItem();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
soItem.setId(node.get("customerId").asText());
JsonNode idmap = node.get("nameIdmap");
Iterator<String> fieldNames = idmap.fieldNames();
while(fieldNames.hasNext()) {
String ip = fieldNames.next();
String textValue = idmap.get(ip).asText();
Pattern p = Pattern.compile("(.*?)=(.*?),(.*?)(\\d+)");
Matcher m = p.matcher(textValue);
if (m.find()) {
soItem.map.put(ip, new SOIPItem(m.group(2), m.group(4)));
}
}
return soItem;
}
}
4. Test class
import java.io.File;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class MicsTest {
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper();
SimpleModule sm = new SimpleModule();
sm.addDeserializer(SOItem.class, new SOCustDeser());
om.registerModule(sm);
SOItem item = om.readValue(new File("c:\\temp\\test.json"), SOItem.class);
System.out.println(item);
}
}
5. Output
SOItem [id=dummy1, map={10.2.1.0=SOIPItem [type=null, id=123], 10.2.1.3=SOIPItem [type=null, id=456], 10.2.1.5=SOIPItem [type=null, id=193], 10.2.1.4=SOIPItem [type=null, id=789]}]
You can get the field names by nameIdmap.getFieldNames as an iterator. You can then iterate over like that:
...
Iterator<String> fieldNames = idmap.getFieldNames();
while(fieldNames.hasNext()) {
String ip = fieldNames.next();
String textValue = idmap.get(ip).getTextValue()
System.out.println(ip + ":" + textValue);
}
If the nested information is also JSON you can then access it further via idmap.get(ip).get("ID"); if not then you still have the option to find it by regex like that:
Pattern p = Pattern.compile("ID=(\\d+)");
Matcher m = p.matcher(textValue);
if(m.find()) {
System.out.println(ip + ":" + m.group(1));
}
Best way to handle these scenarios is to create a matching pojo for your json. This way it gives you flexibility to play around with the data.
Create classes like these
public class Someclass {
private String customerId;
Map<String, String> nameIdmap;
public Map<String, String> getNameIdmap() {
return nameIdmap;
}
public void setNameIdmap(Map<String, String> nameIdmap) {
this.nameIdmap = nameIdmap;
}
public Someclass() {
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
}
And this code will translate your json to SomeClass class
String json = "<copy paste your json here>";
Someclass someclass = objectMapper.readValue(json, Someclass.class);
String s = someclass.getNameIdmap().get("10.2.1.0");
String[] splits = s.split(" ");
String productType = splits[0].split("=")[1];
String id = splits[1].split("=")[1];
System.out.println(productType + " " + id);

Reading a JSON file with multiple attributes

I'm trying to read a JSON file that contains an array of different bikes. When trying to print out the bikes to the java console, i keep getting a null point exception. I'm going to make it so that all the bikes are made into object, but for now just looking on how to print them out.
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("src/bikes.json"));
JSONObject jsonObject = (JSONObject) obj;
//System.out.println(jsonObject);
JSONArray bikeList = (JSONArray) jsonObject.get("BikeList");
Iterator<String> iterator = bikeList.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
JSON File:
{
"Search": {
"BikeList": [
{
"weight": "14.8",
"colour": "Blue",
"price": 149.99,
"name": "Hybrid Pro"
},
{
"weight": "15.8",
"colour": "Red",
"price": 249.99,
"name": "Slant comp"
},
{
"weight": "17.9",
"colour": "Pink",
"price": 500.00,
"name": "Charm"
}
]
}
}
First you have to get the "Search" object. And also you can't just print the object. You need to fetch all the attributes:
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("src/bikes.json"));
JSONObject jsonObject = (JSONObject) obj;
// System.out.println(jsonObject);
JSONObject search = (JSONObject) jsonObject.get("Search");
JSONArray bikeList = (JSONArray) search.get("BikeList");
for (int i = 0; i < bikeList.size(); i++) {
JSONObject bike = (JSONObject) bikeList.get(i);
System.out.println("********************");
System.out.println("Weight: " + bike.get("weight"));
System.out.println("Colour: " + bike.get("colour"));
System.out.println("Price: " + bike.get("price"));
System.out.println("Name: " + bike.get("name"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
Why Don't you try this.
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("src/bikes.json"));
JSONObject jsonObject = (JSONObject) obj;
//System.out.println(jsonObject);
*JSONArray Search= (JSONArray) jsonObject.get("Search");
JSONArray bikeList = (JSONArray) Search.get("BikeList");*
Iterator<String> iterator = bikeList.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
instead of
JSONArray bikeList = (JSONArray) jsonObject.get("BikeList");
you have to use the arrayBuilder like this
JsonArray array = Json.createArrayBuilder().build();
in an example:
[
{ "type": "home", "number": "212 555-1234" },
{ "type": "fax", "number": "646 555-4567" }
]
JsonArray value = Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("type", "home")
.add("number", "212 555-1234"))
.add(Json.createObjectBuilder()
.add("type", "fax")
.add("number", "646 555-4567"))
.build();
quick info here
JsonArray
or here
How to create correct JsonArray in Java using JSONObject
Your object is null because, it does not exist. For that you need to have a schema for JSON document like this,
{
"BikeList": [
The above code contains, a first-level BikeList. Which you would then capture from the code. This is the mistake in your code. I believe, you need to read the Search node first, and then move down to the next one to capture the list,
{
"Search": { // This one first.
"BikeList": [
That way, you would first require to get the Search object, then get the BikeList, otherwise it will always be null.
// Search is an object, not an array.
JSONObject search = (JSONObject) jsonObject.get("Search");
// Find the list in the search object.
Rest of code is the one you already have. This would get the list for you.
Create java Pojos and annotate with Jackson 2
package com.example;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({ "Search" })
public class Bike {
#JsonProperty("Search")
private Search search;
/**
* No args constructor for use in serialization
*
*/
public Bike() {
}
/**
*
* #param search
*/
public Bike(final Search search) {
super();
this.search = search;
}
#JsonProperty("Search")
public Search getSearch() {
return search;
}
#JsonProperty("Search")
public void setSearch(final Search search) {
this.search = search;
}
#Override
public String toString() {
return "Bike [search=" + search + "]";
}
}
package com.example;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({ "BikeList" })
public class Search {
#JsonProperty("BikeList")
private List<BikeList> bikeList = null;
/**
* No args constructor for use in serialization
*
*/
public Search() {
}
/**
*
* #param bikeList
*/
public Search(final List<BikeList> bikeList) {
super();
this.bikeList = bikeList;
}
#JsonProperty("BikeList")
public List<BikeList> getBikeList() {
return bikeList;
}
#JsonProperty("BikeList")
public void setBikeList(final List<BikeList> bikeList) {
this.bikeList = bikeList;
}
#Override
public String toString() {
return "Search [bikeList=" + bikeList + "]";
}
}
package com.example;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({ "weight", "colour", "price", "name" })
public class BikeList {
#JsonProperty("weight")
private String weight;
#JsonProperty("colour")
private String colour;
#JsonProperty("price")
private Double price;
#JsonProperty("name")
private String name;
/**
* No args constructor for use in serialization
*
*/
public BikeList() {
}
/**
*
* #param colour
* #param price
* #param weight
* #param name
*/
public BikeList(final String weight, final String colour, final Double price, final String name) {
super();
this.weight = weight;
this.colour = colour;
this.price = price;
this.name = name;
}
#JsonProperty("weight")
public String getWeight() {
return weight;
}
#JsonProperty("weight")
public void setWeight(final String weight) {
this.weight = weight;
}
#JsonProperty("colour")
public String getColour() {
return colour;
}
#JsonProperty("colour")
public void setColour(final String colour) {
this.colour = colour;
}
#JsonProperty("price")
public Double getPrice() {
return price;
}
#JsonProperty("price")
public void setPrice(final Double price) {
this.price = price;
}
#JsonProperty("name")
public String getName() {
return name;
}
#JsonProperty("name")
public void setName(final String name) {
this.name = name;
}
#Override
public String toString() {
return "BikeList [weight=" + weight + ", colour=" + colour + ", price=" + price + ", name=" + name + "]";
}
}
Then employ Jackson to read input json and convert to Java Objects
package com.example;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
public class Stackoverflow {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final ObjectReader OBJECT_READER_BIKE = OBJECT_MAPPER.readerFor(Bike.class);
public static void main(final String[] args) throws IOException {
final Bike bike = OBJECT_READER_BIKE.readValue(new File("input/bike.json"));
System.out.println(bike);
}
}
output obtained:-
Bike [search=Search [bikeList=[BikeList [weight=14.8, colour=Blue, price=149.99, name=Hybrid Pro], BikeList [weight=15.8, colour=Red, price=249.99, name=Slant comp], BikeList [weight=17.9, colour=Pink, price=500.0, name=Charm]]]]

How to iterate over json data with gson

My json string is:
{
"recordsTotal":1331,
"data":[
{
"part_number":"3DFN64G08VS8695 MS",
"part_type":"NAND Flash",
"id":1154,
"manufacturers":[
"3D-Plus"
]
},
{
"part_number":"3DPM0168-2",
"part_type":"System in a Package (SiP)",
"id":452,
"manufacturers":[
"3D-Plus"
]
},
{
"part_number":"3DSD1G16VS2620 SS",
"part_type":"SDRAM",
"id":269,
"manufacturers":[
"3D-Plus"
]
}
]
}
This code lets me access the two highest level elements:
JsonObject jsonObject = new JsonParser().parse(jsonString).getAsJsonObject();
System.out.println("data : " + jsonObject.get("data"));
System.out.println("recordsTotal : " + jsonObject.get("recordsTotal"));
But what I want to do is iterate over all the objects inside "data" and create a list of part_numbers. How do I do that?
JsonArray is an Iterable<JsonElement>. So you can use for in loop.
JsonObject jsonObject = new JsonParser().parse(jsonString).getAsJsonObject();
final JsonArray data = jsonObject.getAsJsonArray("data");
System.out.println("data : " + data);
System.out.println("recordsTotal : " + jsonObject.get("recordsTotal"));
List<String> list = new ArrayList<String>();
for (JsonElement element : data) {
list.add(((JsonObject) element).get("part_number").getAsString());
}
Suppose class Name for Json Model is Example.
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Example {
#SerializedName("recordsTotal")
private Integer recordsTotal;
#SerializedName("data")
private List<Datum> data = null;
public Integer getRecordsTotal() {
return recordsTotal;
}
public void setRecordsTotal(Integer recordsTotal) {
this.recordsTotal = recordsTotal;
}
public List<Datum> getData() {
return data;
}
public void setData(List<Datum> data) {
this.data = data;
}
}
And suppose List of Data class name is Datum :-
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Datum {
#SerializedName("part_number")
private String partNumber;
#SerializedName("part_type")
private String partType;
#SerializedName("id")
private Integer id;
#SerializedName("manufacturers")
private List<String> manufacturers = null;
public String getPartNumber() {
return partNumber;
}
public void setPartNumber(String partNumber) {
this.partNumber = partNumber;
}
public String getPartType() {
return partType;
}
public void setPartType(String partType) {
this.partType = partType;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<String> getManufacturers() {
return manufacturers;
}
public void setManufacturers(List<String> manufacturers) {
this.manufacturers = manufacturers;
}
}
And then through Gson library we can convert json to java Model :
Example example = new Gson().fromJson(jsonString, new TypeToken<Example>() {}.getType());
Now we can get list of data though example model :-
List<Datum> dataList = example.getData();
From dataList you can traverse and get all info.
If partNmber List we need then we can get in this way :-
List<String> partNumberList = new ArrayList<>();
for (Datum data : dataList) {
partNumberList.add(data.getPartNumber());
}
The given code will not guaranteed to 100% equivalent but it will help you to work.
First you have to create the class for your data objects:
class mydata {
public String part_name;
public String part_type;
public int Id;
public String manufacturers;
}
Your main method should look like
public static void main(String[] args) {
JSONObject obj = new JSONObject();
List<mydata> sList = new ArrayList<mydata>();
mydata obj1 = new mydata();
obj1.setValue("val1");
sList.add(obj1);
mydata obj2 = new mydata();
obj2.setValue("val2");
sList.add(obj2);
obj.put("list", sList);
JSONArray jArray = obj.getJSONArray("list");
for(int ii=0; ii < jArray.length(); ii++)
System.out.println(jArray.getJSONObject(ii).getString("value"));
}
For futher exploration you can use that link:
https://gist.github.com/codebutler/2339666

common dto for two incoming REST json

I want to create a common dto like as shown below for receiving the incoming Manager and Staff details from a REST service
public class Employee {
#JsonProperty("name")
public String name;
#JsonProperty("designation")
public String designation;
#JsonProperty("item")
public String item;
#JsonProperty("item")
public List<Item> items;
//setters and getters
}
The problem is that for for Manager the item field will be a List where as for Staff it will be a string, so I have created two field for item, one for receiving String and another for List, but its not working and I am getting Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token.
The incoming json details is like as shown below
Manager incoming json
{
"name": "Rohit",
"designation": "Manager",
"item": {"name": "ABC", "desc": "1234"}
}
Staff incoming json
{
"name": "Manu",
"designation": "Staff",
"item": "abc"
}
Can anyone please tell me some solution for this
You could create a customer deserializer. If the node for the "item" field is an array, then deserialize it as an array, otherwise deserialize it as a String. For example
public static class EmployeeDeserializer extends JsonDeserializer<Employee> {
#Override
public Employee deserialize(JsonParser jp,
DeserializationContext dc)
throws IOException, JsonProcessingException {
Employee emp = new Employee();
JsonNode root = jp.getCodec().readTree(jp);
emp.name = root.get("name").asText();
emp.designation = root.get("designation").asText();
JsonNode itemNode = root.get("item");
if (itemNode.isArray()) {
ArrayNode itemsNode = (ArrayNode) itemNode;
List<Item> items = new ArrayList<>();
for (JsonNode iNode : itemsNode) {
Item item = new Item();
item.name = iNode.get("name").asText();
item.desc = iNode.get("desc").asText();
items.add(item);
}
emp.items = items;
} else if (itemNode.isObject()) {
List<Item> items = new ArrayList<>();
Item item = new Item();
item.name = itemNode.get("name").asText();
item.desc = itemNode.get("desc").asText();
items.add(item);
emp.items = items;
} else {
String item = root.get("item").asText();
emp.item = item;
}
return emp;
}
}
I actually added three cases for "item". It could be a JSON array as multiple Items, a JSON object (which is what you have in your post) as a single Item, or a String for the staff. If it's a JSON object, I just create the single Item and added it to a List
Here is a complete test
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
public class EmployeeTest {
#JsonDeserialize(using = EmployeeDeserializer.class)
public static class Employee {
public String name;
public String designation;
public String item;
public List<Item> items;
}
public static class Item {
public String name;
public String desc;
#Override
public String toString() {
return "Item{" + "name=" + name + ", desc=" + desc + '}';
}
}
public static class EmployeeDeserializer extends JsonDeserializer<Employee> {
#Override
public Employee deserialize(JsonParser jp,
DeserializationContext dc)
throws IOException, JsonProcessingException {
Employee emp = new Employee();
JsonNode root = jp.getCodec().readTree(jp);
emp.name = root.get("name").asText();
emp.designation = root.get("designation").asText();
JsonNode itemNode = root.get("item");
if (itemNode.isArray()) {
ArrayNode itemsNode = (ArrayNode) itemNode;
List<Item> items = new ArrayList<>();
for (JsonNode iNode : itemsNode) {
Item item = new Item();
item.name = iNode.get("name").asText();
item.desc = iNode.get("desc").asText();
items.add(item);
}
emp.items = items;
} else if (itemNode.isObject()) {
List<Item> items = new ArrayList<>();
Item item = new Item();
item.name = itemNode.get("name").asText();
item.desc = itemNode.get("desc").asText();
items.add(item);
emp.items = items;
} else {
String item = root.get("item").asText();
emp.item = item;
}
return emp;
}
}
private static ObjectMapper mapper;
#BeforeClass
public static void setUpMapper() {
mapper = new ObjectMapper();
//SimpleModule module = new SimpleModule();
//module.addDeserializer(Employee.class, new EmployeeDeserializer());
//mapper.registerModule(module);
}
#Test
public void should_deserialize_manager_list_ok() throws Exception {
final String mgrJson
= "{\n"
+ " \"name\": \"Rohit\",\n"
+ " \"designation\": \"Manager\",\n"
+ " \"item\": [{\"name\": \"ABC\", \"desc\": \"1234\"}]\n"
+ "}";
Employee mgr = mapper.readValue(mgrJson, Employee.class);
assertEquals("Rohit", mgr.name);
assertEquals("Manager", mgr.designation);
assertNull(mgr.item);
assertEquals(1, mgr.items.size());
assertEquals("ABC", mgr.items.get(0).name);
assertEquals("1234", mgr.items.get(0).desc);
}
#Test
public void should_deserialize_staff_string_ok() throws Exception {
final String staffJson
= "{\n"
+ " \"name\": \"Manu\",\n"
+ " \"designation\": \"Staff\",\n"
+ " \"item\": \"abc\"\n"
+ "}";
Employee staff = mapper.readValue(staffJson, Employee.class);
assertEquals("Manu", staff.name);
assertEquals("Staff", staff.designation);
assertEquals("abc", staff.item);
assertNull(staff.items);
}
#Test
public void should_deserialize_single_item_ok() throws Exception {
final String mgrJson
= "{\n"
+ " \"name\": \"Rohit\",\n"
+ " \"designation\": \"Manager\",\n"
+ " \"item\": {\"name\": \"ABC\", \"desc\": \"1234\"}\n"
+ "}";
Employee mgr = mapper.readValue(mgrJson, Employee.class);
assertEquals("Rohit", mgr.name);
assertEquals("Manager", mgr.designation);
assertNull(mgr.item);
assertEquals(1, mgr.items.size());
assertEquals("ABC", mgr.items.get(0).name);
assertEquals("1234", mgr.items.get(0).desc);
}
}
You can make Manager and Staff extend an abstract class Employee, and then use the 'designation' JSON property to distinguish them:
// note hashCode(), equals() and toString() methods left out for brevity!
#JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "designation")
#JsonSubTypes({ #JsonSubTypes.Type(Staff.class), #JsonSubTypes.Type(Manager.class) })
public static abstract class Employee {
#JsonProperty("name")
public String name;
public Employee(String name) {
this.name = name;
}
public Employee() {
}
}
#JsonTypeName("Manager")
public static final class Manager extends Employee {
#JsonProperty("item")
public List<Item> items;
public Manager(String name, List<Item> items) {
super(name);
this.items = items;
}
public Manager() {
}
public static final class Item {
public final String name;
public final String desc;
public Item(#JsonProperty("name") String name, #JsonProperty("desc") String desc) {
this.name = name;
this.desc = desc;
}
}
}
#JsonTypeName("Staff")
public static final class Staff extends Employee {
#JsonProperty("item")
public String item;
public Staff(String name) {
super(name);
this.item = item;
}
public Staff() {
}
}
Tests:
#Test
public void polymorphic_deserialization_of_manager() throws Exception {
ObjectMapper mapper = new ObjectMapper().enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.enable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);
String json = "{ name: 'Rohit', designation: 'Manager', item: { name: 'ABC', desc: '1234' } }";
Employee employee = new Manager("Rohit", ImmutableList.of(new Manager.Item("ABC", "1234")));
assertThat(mapper.readValue(json, Employee.class), equalTo(employee));
assertThat(mapper.writeValueAsString(employee), equivalentTo(json));
}
#Test
public void polymorphic_deserialization_of_staff() throws Exception {
ObjectMapper mapper = new ObjectMapper().enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES).enable(
JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
String json = "{ name: 'Manu', designation: 'Staff', item: 'abc' }";
Employee employee = new Staff("Manu", "abc");
assertThat(mapper.readValue(json, Employee.class), equalTo(employee));
assertThat(mapper.writeValueAsString(employee), equivalentTo(json));
}

Categories