How to parse a JSON string to an array using Jackson - java

I have a String with the following value:
[
{
"key1": "value11",
"key2": "value12"
},
{
"key1": "value21",
"key2": "value22"
}
]
And the following class:
public class SomeClass {
private String key1;
private String key2;
/* ... getters and setters omitted ...*/
}
And I want to parse it to a List<SomeClass> or a SomeClass[]
Which is the simplest way to do it using Jackson ObjectMapper?

I finally got it:
ObjectMapper objectMapper = new ObjectMapper();
TypeFactory typeFactory = objectMapper.getTypeFactory();
List<SomeClass> someClassList = objectMapper.readValue(jsonString, typeFactory.constructCollectionType(List.class, SomeClass.class));

The other answer is correct, but for completeness, here are other ways:
List<SomeClass> list = mapper.readValue(jsonString, new TypeReference<List<SomeClass>>() { });
SomeClass[] array = mapper.readValue(jsonString, SomeClass[].class);

The complete example with an array.
Replace "constructArrayType()" by "constructCollectionType()" or any other type you need.
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
public class Sorting {
private String property;
private String direction;
public Sorting() {
}
public Sorting(String property, String direction) {
this.property = property;
this.direction = direction;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public static void main(String[] args) throws JsonParseException, IOException {
final String json = "[{\"property\":\"title1\", \"direction\":\"ASC\"}, {\"property\":\"title2\", \"direction\":\"DESC\"}]";
ObjectMapper mapper = new ObjectMapper();
Sorting[] sortings = mapper.readValue(json, TypeFactory.defaultInstance().constructArrayType(Sorting.class));
System.out.println(sortings);
}
}

I sorted this problem by verifying the json on JSONLint.com and then using Jackson. Below is the code for the same.
Main Class:-
String jsonStr = "[{\r\n" + " \"name\": \"John\",\r\n" + " \"city\": \"Berlin\",\r\n"
+ " \"cars\": [\r\n" + " \"FIAT\",\r\n" + " \"Toyata\"\r\n"
+ " ],\r\n" + " \"job\": \"Teacher\"\r\n" + " },\r\n" + " {\r\n"
+ " \"name\": \"Mark\",\r\n" + " \"city\": \"Oslo\",\r\n" + " \"cars\": [\r\n"
+ " \"VW\",\r\n" + " \"Toyata\"\r\n" + " ],\r\n"
+ " \"job\": \"Doctor\"\r\n" + " }\r\n" + "]";
ObjectMapper mapper = new ObjectMapper();
MyPojo jsonObj[] = mapper.readValue(jsonStr, MyPojo[].class);
for (MyPojo itr : jsonObj) {
System.out.println("Val of getName is: " + itr.getName());
System.out.println("Val of getCity is: " + itr.getCity());
System.out.println("Val of getJob is: " + itr.getJob());
System.out.println("Val of getCars is: " + itr.getCars() + "\n");
}
POJO:
public class MyPojo {
private List<String> cars = new ArrayList<String>();
private String name;
private String job;
private String city;
public List<String> getCars() {
return cars;
}
public void setCars(List<String> cars) {
this.cars = cars;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
} }
RESULT:-
Val of getName is: John
Val of getCity is: Berlin
Val of getJob is: Teacher
Val of getCars is: [FIAT, Toyata]
Val of getName is: Mark
Val of getCity is: Oslo
Val of getJob is: Doctor
Val of getCars is: [VW, Toyata]

Related

How do I get an array value instead of reference from ObjectMapper in Jackson?

I am trying to get a result from an API response and am able to map everything except for columnHeaders, which is an array of ColumnHeaders. I am instead getting a reference to an array. The code is below.
Response Class
public class Response {
#JsonProperty("searchApiFormatVersion")
private String searchApiFormatVersion;
#JsonProperty("searchName")
private String searchName;
#JsonProperty("description")
private String description;
#JsonProperty("columnHeaders")
private ColumnHeader[] columnHeaders;
public Response(String searchApiFormatVersion, String searchName, String description,
ColumnHeader[] columnHeaders) {
this.searchApiFormatVersion = searchApiFormatVersion;
this.searchName = searchName;
this.description = description;
this.columnHeaders = columnHeaders;
}
public Response(){
}
public String getSearchApiFormatVersion() {
return searchApiFormatVersion;
}
public void setSearchApiFormatVersion(String searchApiFormatVersion) {
this.searchApiFormatVersion = searchApiFormatVersion;
}
public String getSearchName() {
return searchName;
}
public void setSearchName(String searchName) {
this.searchName = searchName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ColumnHeader[] getColumnHeaders() {
return columnHeaders;
}
public void setColumnHeaders(ColumnHeader[] columnHeaders) {
this.columnHeaders = columnHeaders;
}
#Override
public String toString() {
return "Response{" +
"searchApiFormatVersion='" + searchApiFormatVersion + '\'' +
", searchName='" + searchName + '\'' +
", description='" + description + '\'' +
", totalRowCount=" + totalRowCount +
", returnedRowCount=" + returnedRowCount +
", startingReturnedRowNumber=" + startingReturnedRowNumber +
", basetype='" + basetype + '\'' +
", columnCount=" + columnCount +
", columnHeaders=" + columnHeaders +
'}';
}
}
ColumnHeader class
public class ColumnHeader {
#JsonProperty("text")
private String text;
#JsonProperty("dataType")
private String dataType;
#JsonProperty("hierarchy")
private int hierarchy;
#JsonProperty("parentName")
private String parentName;
#JsonProperty("isEntity")
private Boolean isEntity;
#JsonProperty("isEset")
private Boolean isEset;
public ColumnHeader(String text, String dataType, int hierarchy, String parentName, Boolean isEntity, Boolean isEset) {
this.text = text;
this.dataType = dataType;
this.hierarchy = hierarchy;
this.parentName = parentName;
this.isEntity = isEntity;
this.isEset = isEset;
}
public ColumnHeader(){
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getHierarchy() {
return hierarchy;
}
public void setHierarchy(int hierarchy) {
this.hierarchy = hierarchy;
}
public String getParentName() {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
public Boolean getEntity() {
return isEntity;
}
public void setEntity(Boolean entity) {
isEntity = entity;
}
public Boolean getEset() {
return isEset;
}
public void setEset(Boolean eset) {
isEset = eset;
}
#Override
public String toString() {
return "ColumnHeader{" +
"text='" + text + '\'' +
", dataType='" + dataType + '\'' +
", hierarchy=" + hierarchy +
", parentName='" + parentName + '\'' +
", isEntity=" + isEntity +
", isEset=" + isEset +
'}';
}
}
Service Class
public class BudgetEffortResponseService {
Logger logger = LoggerFactory.getLogger(Response.class);
public Response getResponseFromStringJsonApiResponse(String stringJsonResponse) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper(); //Used to map objects from JSON values specified in Award under #JsonProperty annotation
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject stringJsonResponseTurnedIntoJsonObject = new JSONObject(stringJsonResponse);
logger.info("stringJsonResponseTurnedIntoJsonObject: " + stringJsonResponseTurnedIntoJsonObject);
return objectMapper.readValue(stringJsonResponseTurnedIntoJsonObject.toString(), Response.class);
}
}
Main Class
#SpringBootApplication
public class EtlApplication {
public static final String API_USERNAME = System.getenv("API_USERNAME");
public static final String API_PASSWORD = System.getenv("API_PASSWORD");
public static final String API_PREFIX = System.getenv("API_PREFIX");
public static final String API_PATH = System.getenv("API_PATH");
public static void main(String[] args) throws URISyntaxException, JsonProcessingException {
Logger logger = LoggerFactory.getLogger(EtlApplication.class);
logger.info("--------------------Starting process--------------------");
AwardRepository awardRepository = new AwardRepository();
AwardService awardService = new AwardService();
ApiResponseRowService apiResponseRowService = new ApiResponseRowService();
ApiResponseRepository apiResponseRepository = new ApiResponseRepository();
BudgetEffortResponseService budgetEffortResponseService = new BudgetEffortResponseService();
Date startDateForApiPull = new GregorianCalendar(2023, Calendar.FEBRUARY, 1).getTime();
Date endDateForApiPull = new GregorianCalendar(2023, Calendar.FEBRUARY, 2).getTime();
logger.info("============Starting BudgetEffort API pull from Huron===============");
HttpResponse<String> budgetEffortHttpResponse = apiResponseRepository.getHttpResponseFromApi(startDateForApiPull,
endDateForApiPull, 1, -1, API_PREFIX, API_PATH,
API_USERNAME, API_PASSWORD);
logger.info("BudgetEffortHttpResponse: " + budgetEffortHttpResponse);
logger.info("============End of BudgetEffort API pull from Huron===============");
//Get body of http response string
String budgetEffortResponseString = budgetEffortHttpResponse.body();
logger.info("BudgetEffortResponseString: " + budgetEffortResponseString);
Response budgetEffortResponse = budgetEffortResponseService.getResponseFromStringJsonApiResponse(budgetEffortResponseString);
logger.info("BudgetEffortResponse: " + budgetEffortResponse);
logger.info("--------------------End of process--------------------");
}
}
The response. I'm noticing that I'm getting the reference to the array for columnHeaders and not the values. How would I get the values? Thank you.
BudgetEffortResponse: Response{searchApiFormatVersion='1.0', searchName='Personnel Details for Authorized allocations on Active Awards', description='', columnHeaders=[Lcom.example.etl.entity.budgetEffort.ColumnHeader;#7a7471ce}
The response you get is ok. And also the Array is good. The line
logger.info("BudgetEffortResponse: " + budgetEffortResponse);
uses an indirect cast to String of the Object budgetEffortResponse. In this case all toString() methods of the objects are called. What you need to do in order to print out the Objects is to implement/add the toString() method in the class com.example.etl.entity.budgetEffort.ColumnHeader
Update:
As the toString method is already implemented, the above is partially wrong. But there is a way to use a setting of the ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(budgetEffortResponse);
logger.info("BudgetEffortResponse: " + json);

Right way to manage nested data

I'm making a Shopping app which gets product attributes from the server. The Json Array I get from the server contains nested Json objects and Json arrays which look likes this:
[
"id": 1860,
"name": "T-Shirt",
"attributes": [
{
"id": 1,
"name": "color",
"position": 0,
"visible": true,
"variation": false,
"options": [
"blue",
"green",
"red"
]
},
{
"id": 2,
"name": "size",
"position": 3,
"visible": true,
"variation": false,
"options": [
"L",
"M",
"XL",
"XXL"
]
}
],
I created a class for managing product variables which contains of strings and ints and setters and getters for simple variable types like name,price etc.
public class Product {
//a class holding product objects for managing through app
public void setProductName(String productName) {
this.productName = productName;
}
private String productName;
private String productPrice;
private String oldPrice;
private int attrCount;
HashMap<String, ArrayList<String>> attrs;
private String description;
private boolean isLoading = false;
private boolean isNew = false;
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
private String imageUrl="";
public Product( String productName, String productPrice, boolean isNew,String imageUrl) {
this.productName = productName;
this.productPrice = productPrice;
this.isNew = isNew;
this.imageUrl=imageUrl;
}
public Product() {
}
public boolean isNew() {
return isNew;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
public String getProductName() {
return productName;
}
But for managing attributes I need a way to bind each attribute name with its options to keep track of them in future.
Because the attributes and options coming from the server are varied each time I can't use something like enums.
I tried to store the data using HashMap<String,ArrayList> in my products class which takes the attribute as a key and option arrays as values.
HashMap<String,ArrayList<String>>attrs=new HashMap<>();
for (int j=0;j<attrJsonArray.length();j++){
JSONArray optionJsonArray=new JSONArray(attrJsonArray.getJSONObject(j).getString("options"));
ArrayList<String>attrsOptionArray= new ArrayList<>();
for(int k=0;k<optionJsonArray.length();k++){
attrsOptionArray.add(optionJsonArray.getString(k));
}
attrs.put(attrJsonArray.getJSONObject(j).getString("name"),attrsOptionArray);
}
but it seems like a bad practice. I wonder what is the right way to store this kind of data.
You can parse json to java class.
1.Use com.fasterxml.jackson.databind.ObjectMapper for parsing json.
com.fasterxml.jackson.databind.ObjectMapper objectMapper = new ObjectMapper();
Product product = objectMapper.readValue(dataOfJson, Product.class);
2.Make java class for json.
Key of json is field name or name of #JsonProperty.
Array of json is List or array.
If exist The deeper field like "attributes",Use nested static class.
class Product {
#JsonProperty("name")
private String productName;
private String id;
... other field
private List<Attributes> attributes;
// set and get method
static class Attributes{
private String id;
private List<String> options;
... other field
//set and get method
}
}
If you want to try testing, Use this. But I changed a little your json because Your json is not completed.
public class JsonToPojo {
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
String dataOfJson = " {\r\n"
+ " \"id\": 1860,\r\n"
+ " \"name\": \"T-Shirt\",\r\n"
+ "\r\n"
+ " \"attributes\": [{\r\n"
+ " \"id\": 1,\r\n"
+ " \"name\": \"color\",\r\n"
+ " \"position\": 0,\r\n"
+ " \"visible\": true,\r\n"
+ " \"variation\": false,\r\n"
+ " \"options\": [\r\n"
+ " \"blue\",\r\n"
+ " \"green\",\r\n"
+ " \"red\"\r\n"
+ " ]\r\n"
+ " },\r\n"
+ "\r\n"
+ " {\r\n"
+ " \"id\": 2,\r\n"
+ " \"name\": \"size\",\r\n"
+ " \"position\": 3,\r\n"
+ " \"visible\": true,\r\n"
+ " \"variation\": false,\r\n"
+ " \"options\": [\r\n"
+ " \"L\",\r\n"
+ " \"M\",\r\n"
+ " \"XL\",\r\n"
+ " \"XXL\"\r\n"
+ " ]\r\n"
+ " }\r\n"
+ " ]\r\n"
+ "}";
com.fasterxml.jackson.databind.ObjectMapper objectMapper = new ObjectMapper();
Product product = objectMapper.readValue(dataOfJson, Product.class);
System.out.println(product);
}
}
class Product {
#JsonProperty("name")
private String productName;
private String id;
private List<Attributes> attributes;
static class Attributes{
private String id;
private String name;
private int position;
private boolean visible;
private boolean variation;
private List<String> options;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVariation() {
return variation;
}
public void setVariation(boolean variation) {
this.variation = variation;
}
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
#Override
public String toString() {
return "Attributes [id=" + id + ", name=" + name + ", position=" + position + ", visible=" + visible
+ ", variation=" + variation + ", options=" + options + "]";
}
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Attributes> getAttributes() {
return attributes;
}
public void setAttributes(List<Attributes> attributes) {
this.attributes = attributes;
}
#Override
public String toString() { // for printing output
return "Product [productName=" + productName + ", id=" + id + ", attributes=" + attributes + "]";
}
}

Parser works for some ArrayLists, throws Expected BEGIN_OBJECT but was STRING for others

I had issues with this but read other questions on Stack Overflow and initially solved the problems. Now I can send JSON between my Client and Server and create objects from this JSON in the Client. However, I keep getting this error with one specific object:
client.restaurant = gson.fromJson(obj.get("restaurant"), Restaurant.class); // works
client.postcodes = gson.fromJson(obj.get("postcodes"), new TypeToken<ArrayList<Postcode>>(){}.getType()); // works
client.orders = gson.fromJson(obj.get("orders"), new TypeToken<ArrayList<Order>>(){}.getType()); // java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at path $[0].dishes.updateListeners
All the JSON is valid as per https://jsonlint.com. I have no idea how to find out more about this issue, but one thing I tried was I extracted the JSON for ArrayList<Order> orders and tried to parse it manually:
JsonObject testOrder = parser.parse("{\n" +
" \"orders\": [\n" +
" {\n" +
" \"user\": {\n" +
" \"userName\": \"Admin\",\n" +
" \"password\": \"password\",\n" +
" \"address\": \"University Road\",\n" +
" \"postcode\": {\n" +
" \"postcodeName\": \"SO17 1BJ\",\n" +
" \"latLong\": {\n" +
" \"lon\": 0.0,\n" +
" \"lat\": 0.0\n" +
" },\n" +
" \"distance\": 0,\n" +
" \"updateListeners\": []\n" +
" },\n" +
" \"updateListeners\": []\n" +
" },\n" +
" \"dishes\": {\n" +
" \"Sushi Roll\": 5,\n" +
" \"Side Rice\": 2\n" +
" },\n" +
" \"name\": \"07/05/2019 10:23:08\",\n" +
" \"updateListeners\": []\n" +
" }\n" +
" ]\n" +
"}").getAsJsonObject();
client.orders = gson.fromJson(testOrder, new TypeToken<ArrayList<Order>>(){}.getType()));
but this also doesn't work (the error is subtly different -- Expected BEGIN_ARRAY but was BEGIN_OBJECT).
Edit:
Order.java
package comp1206.sushi.common;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import comp1206.sushi.common.Order;
public class Order extends Model implements Serializable {
private String status;
private User user;
private HashMap<Dish, Number> dishes = new HashMap<Dish, Number>();
public Order() {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/YYYY HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
this.name = dtf.format(now);
}
public Order(User user) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/YYYY HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
this.name = dtf.format(now);
setUser(user);
}
public Order(User user, Map<Dish, Number> basket) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/YYYY HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
this.name = dtf.format(now);
setUser(user);
basket.forEach((k,v)->addDishes(k,v));
}
public Number getDistance() {
return 1;
}
#Override
public String getName() {
return this.name;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
notifyUpdate("status",this.status,status);
this.status = status;
}
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return this.user;
}
public void addDishes(Dish dish, Number quantity) {
// may need to call notifyUpdate?
dishes.put(dish, quantity);
}
public void editDishes(Dish dish, Number quantity) {
dishes.replace(dish, quantity);
}
public void clearDishes() {
dishes.clear();
}
public Number getCost() {
int total = 0;
for (Map.Entry<Dish, Number> entry : dishes.entrySet()) {
int temptotal1 = (int) entry.getKey().getPrice();
int temptotal2 = (int) entry.getValue();
total += (temptotal1*temptotal2);
}
return total;
}
public Map<Dish, Number> getOrderContents() {
return dishes;
}
}
Postcode.java:
package comp1206.sushi.common;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import comp1206.sushi.common.Postcode;
public class Postcode extends Model implements Serializable {
private static final long serialVersionUID = -2179416792423154920L;
private String postcodeName;
private Map<String,Double> latLong;
private Number distance;
public Postcode(String code) {
this.postcodeName = code;
calculateLatLong();
this.distance = Integer.valueOf(0);
}
public Postcode(String code, Restaurant restaurant) {
this.postcodeName = code;
calculateLatLong();
calculateDistance(restaurant);
}
#Override
public String getName() {
return this.postcodeName;
}
public void setName(String name) {
this.postcodeName = name;
}
public Number getDistance() {
return this.distance;
}
public Map<String,Double> getLatLong() {
return this.latLong;
}
protected void calculateDistance(Restaurant restaurant) {
//This function needs implementing
Postcode destination = restaurant.getLocation();
this.distance = Integer.valueOf(0);
}
protected void calculateLatLong() {
//This function needs implementing
this.latLong = new HashMap<String,Double>();
latLong.put("lat", 0d);
latLong.put("lon", 0d);
this.distance = new Integer(0);
}
}
So I think your problem is around this:
"dishes": {
"Sushi Roll": 5,
"Side Rice": 2
}
It tries to invoke method of Order addDishes(Dish dish, Number quantity) but it fails, because It has "Sushi Roll" instead of whole object which represents the Dish. You need to update Json instead of string to have object which match constructor of Dish. Something like:
"dishes": {
{"name":"Sushi Roll","description":"", "price":0.0, "restockThreshold": 0, "restockAmount":0}: 5,
{"name":"Side Rice","description":"", "price":0.0, "restockThreshold": 0, "restockAmount":0}: 2
}
In general when dealing with Json you need to follow some rules.
Always put default constructor with no arguments to data objects.
Try to keep all collections with getter and setter.

How to convert the following JSON String to POJO

I want to convert the following JSON string to a Java object:
{
"user": {
"0": {
"firstName": "Monica",
"lastName": "Belluci"
},
"1": {
"firstName": "John",
"lastName": "Smith"
},
"2": {
"firstName": "Owen",
"lastName": "Hargreaves"
}
}
}
To convert this to Java object I've created the following classes:
class User {
private Map<String, MyObject> user = new HashMap<>();
//Getter and Setter is here
}
class MyObject {
private String firstName;
private String lastName;
//Getters and Setters are here
}
I'm using Jackson library to convert JSON to Java. Here is how I'm using the Jackson for conversion:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(jsonString, User.class);
The problem is that with this conversion above the Map inside the User object is always empty. What am I doing wrong?
Thanks in advance.
I think it should work. I've executed this code and it works fine. Here is my example.
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class TestJackson {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
String testJson = "{\n" + " \"user\": {\n" + " \"0\": {\n" + " \"firstName\": \"Monica\",\n" + " \"lastName\": \"Belluci\"\n" + " },\n" + " \"1\": {\n" + " \"firstName\": \"John\",\n" + " \"lastName\": \"Smith\"\n" + " },\n" + " \"2\": {\n" + " \"firstName\": \"Owen\",\n" + " \"lastName\": \"Hargreaves\"\n" + " }\n" + " }\n" + "}";
User readValue = mapper.readValue(testJson, User.class);
System.out.println("readValue = " + readValue);
}
}
and the User.class:
import java.util.HashMap;
import java.util.Map;
class User {
private Map<String, MyObject> user = new HashMap<String, MyObject>();
public Map<String, MyObject> getUser() {
return user;
}
public void setUser(Map<String, MyObject> user) {
this.user = user;
}
#Override
public String toString() {
return "User{" +
"user=" + user +
'}';
}
}
class MyObject {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return "MyObject{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
Use can done with the help of gson library.
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JsonToJava {
public static void main(String[] args) throws IOException {
try(Reader reader = new InputStreamReader(JsonToJava.class.getResourceAsStream("/Server2.json"), "UTF-8")){
Gson gson = new GsonBuilder().create();
Person p = gson.fromJson(reader, YourPOJOClass.class);
System.out.println(p);
}
}
}
visit this link hope this helps :)
I had one additional issue, that i faced when converting JSON to Java POJO: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of class out of START_ARRAY token ...
If anyone faces this issue, this is because JSON is expecting an object {} but it sees an array [{}] within the JSON String that is passed in
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(jsonString, User.class);
To fix
User[] user = mapper.readValue(jsonString, User[].class);
Reference: https://stackoverflow.com/a/33515796/4167786
You can try below code, It works fine..
public class User {
private Map<String, Map<String, String>> user;
public Map<String, Map<String, String>> getUser() {
return user;
}
public void setUser(Map<String, Map<String, String>> user) {
this.user = user;
}
}
public class JsonCast {
public static void main(String args[]) {
String response = "{\"user\" : {\"0\": {\"firstName\": \"Monica\",\"lastName\": \"Belluci\"},\"1\": { \"firstName\": \"John\",\"lastName\": \"Smith\"}}}";
ObjectMapper mapper = new ObjectMapper();
try {
User user = mapper.readValue(response, User.class);
System.out.println(user.getUser().get("0"));
} catch (IOException e) {
e.printStackTrace();
}
}
}

How to convert JSON object from third party api into local POJO

Let's say i make a call to a thrid party API to get a object Task and I get the following JSON String in return:
{
"tasks": [
{
"id": 1,
"code": "CODE",
"description": "Dummy Task",
"withConfirmation": false,
"resource": {
"id": "abcdef12-fe14-57c4-acb5-1234e7456d62",
"group": "Doctor",
"firstname": "Toto",
"lastname": "Wallace",
},
{
"id": 2,
"code": "CODE",
"description": "Dummyyy Taaask",
"withConfirmation": false
}
]
}
In the returned json we have a Task which can be joined with a Resource.
In our system, a Task is as the following:
#JsonAutoDetect
public class Task implements Serializable {
private Integer id;
private String code = "BASIC";
private String description;
private boolean withConfirmation = false;
/**
* CONSTRUCTOR
*/
public Task() {
}
public Integer getId() {
return id;
}
#JsonProperty
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#JsonProperty
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#JsonProperty
public boolean isWithConfirmation() {
return withConfirmation;
}
public void setWithConfirmation(boolean withConfirmation) {
this.withConfirmation = withConfirmation;
}
public String toString() {...
}
}
and a Resource looks like that:
public class Resource implements Serializable {
...
private String firstname;
private String lastname;
private MedicalGroup group; // id + name + description
private Set<Task> tasks = new HashSet<Task>(0);
...
// getters and setters and toString etc.
...
}
So the major difference, aside from the field names is that a Task does not contain any Resource but the relation is rather in the opposite direction which means that a Resource can hold n Task.
What would be for this case the best way to serialize the returned json object from the third party and convert/map it to a pojo from my own system?
I'm currently reading Gson doc in order to try it but any suggestion is welcomed.
This code has to be easily reusable cause it's going to be needed inside multiple projects.
It is not full working code, because i have no idea how you want to work with Resource. Should Json create new resource or try to find already existing one. How will you create MedicalGroup from json, because it is not enuogh data for that. I was going to ask this in comments, but there is not enough space. And here is demo how you can try to solve most of the problems except the Resources to/from json mapping.
Main idea is to add #JsonAnyGetter public Map<String, Object> getAdditionalProperties() and #JsonAnySetter public void setAdditionalProperty(String name, Resource value) in your Task POJO:
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
HashMap<String, Object> map= new HashMap<>();
// IMPORTANT
// here we can try to find resource that has this task
// and export its info to json like this:
// CHANGE THIS
Resource res = new Resource();
res.firstname = "Toto";
res.lastname = "Wallace";
// IMPORTANT END
map.put("resource", res);
return map;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Resource value) {
// IMPORTANT
// Here you have to create or find appropriate Resource in your code
// and add current task to it
System.out.println(name+" "+ value );
}
FULL Demo:
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
public class Main3 {
private static String json = "{\n" +
" \"tasks\": [\n" +
" {\n" +
" \"id\": 1,\n" +
" \"code\": \"CODE\",\n" +
" \"description\": \"Dummy Task\",\n" +
" \"withConfirmation\": false,\n" +
" \"resource\": {\n" +
" \"id\": \"abcdef12-fe14-57c4-acb5-1234e7456d62\",\n" +
" \"group\": \"Doctor\",\n" +
" \"firstname\": \"Toto\",\n" +
" \"lastname\": \"Wallace\"\n" +
" }},\n" +
" {\n" +
" \"id\": 2,\n" +
" \"code\": \"CODE\",\n" +
" \"description\": \"Dummyyy Taaask\",\n" +
" \"withConfirmation\": false\n" +
" }\n" +
" ]\n" +
" }";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
TasksList tl = mapper.readValue(json, TasksList.class);
String result = mapper.writeValueAsString(tl);
System.out.println(result);
}
private static class TasksList {
#JsonProperty(value = "tasks")
private List<Task> tasks;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Resource implements Serializable {
#JsonProperty(value = "firstname")
private String firstname;
#JsonProperty(value = "lastname")
private String lastname;
// HAVE NO IDEA HOW YOU GONNA MAP THIS TO JSON
// private MedicalGroup group; // id + name + description
private Set<Task> tasks = new HashSet<Task>(0);
#Override
public String toString() {
return "Resource{" +
"firstname='" + firstname + '\'' +
", lastname='" + lastname + '\'' +
", tasks=" + tasks +
'}';
}
}
#JsonAutoDetect
public static class Task implements Serializable {
private Integer id;
private String code = "BASIC";
private String description;
private boolean withConfirmation = false;
/**
* CONSTRUCTOR
*/
public Task() {
}
public Integer getId() {
return id;
}
#JsonProperty
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#JsonProperty
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#JsonProperty
public boolean isWithConfirmation() {
return withConfirmation;
}
public void setWithConfirmation(boolean withConfirmation) {
this.withConfirmation = withConfirmation;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
HashMap<String, Object> map= new HashMap<>();
// IMPORTANT
// here we can try to find resource that has this task
// and export its info to json like this:
// CHANGE THIS
Resource res = new Resource();
res.firstname = "Toto";
res.lastname = "Wallace";
// IMPORTANT END
map.put("resource", res);
return map;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Resource value) {
// IMPORTANT
// Probably here you have to create or find appropriate Resource in your code
// and add current task to it
System.out.println(name+" "+ value );
}
#Override
public String toString() {
return "Task{" +
"id=" + id +
", code='" + code + '\'' +
", description='" + description + '\'' +
", withConfirmation=" + withConfirmation +
'}';
}
}
}
you can use Gson library by google to convert Json to Pojo Class.
new Gson().fromJson(jsonString,Response.class);

Categories