How to map multiple JSON responses to a single Java POJO? - java

Need to map multiple types of JSON responses to a single POJO so that I can compare the different objects to provide insight about the differences.
I had tried mapping the first response to the POJO and parsed the second response to populate the defined POJO:
class XXX {
#JsonProperty("accountHolder")
private String accountHolder;
#JsonProperty("routingNumber")
private String routingNumber;
#JsonProperty("balance")
private List<Balance> balance;
#JsonProperty("accountName")
private String accountName;
#JsonProperty("bankTransferCodeType")
private String bankTransferCodeType;
#JsonProperty("individualInformation")
private IndividualInformation individualInformation;
#JsonProperty("acctType")
private String acctType;
#JsonProperty("transactionList")
private TransactionList transactionList;
#JsonProperty("accountNumber")
private String accountNumber;
#JsonProperty("uniqueId")
private String uniqueId;
#JsonProperty("bankNetID")
private String bankNetID;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
}
First response:
[
{
"ACCOUNT_NAME": "",
"ACCOUNT_NUMBER": "",
"AVAILABLE_BALANCE": null,
"CURRENT_BALANCE": "",
"FULL_ACCOUNT_NUMBER": null,
}
]
Second response:
"bankAccount": [
{
"accountName": "",
"accountNumber": "",
"routingNumber": "",
"fullAccountNumber": "",
"bankTransferCodeType": "",
"acctType": "",
"transactionList": {
"transaction": [
{
"amount": {
"curCode": "",
"content": ""
}
],
"oldestTxnDate": ""
},
"uniqueId":
}
}
Expecting a generic way to map the different structured JSON entities to single POJO.

How to map multiple JSON responses to a single Java POJO?
As both responses seem to be completely different from each other, with nothing in common, I would refrain from attempting to use a single class for reading both responses.
Expecting a generic way to map the different structured JSONs to single POJO.
You could parse both responses as a Map<String, Object> and then map the values to a common class.
You could create separated classes for mapping each response. It will allow you to decouple them and evolve them as you need. You also can use use mapping frameworks such as MapStruct for reducing the boilerplate code when mapping from one object to another.

It doesn’t seems to have any generic way. But you can do this:
Create multiple domain classes for each response type
Create a single standard domain class
Create mapper for each response class to map that to standard domain
class. You can use MapStruct reference here

I would suggest using Jackson Json Views. Here is an example for the same :
Example
public class Views {
public class Global {
}
public class Internal extends Global {
}
}
class XXX {
#JsonView(Views.Global.class)
#JsonProperty("accountHolder")
private String accountHolder;
#JsonView(Views.Internal.class)
#JsonProperty("routingNumber")
private String routingNumber;
}
Hope it helps.

What I did is I created a MyResponse model containing basically all response fields from the JSON response you expect to get.
MyResponse has c-tor or receiving these fields or setters allowing setting them.
Then I created some kind of service class MyService that can issue multiple requests and gets responses back.
Then you just do something like this in some kind of manager class or whatever you call it:
MyService mySer = new MyService();
MyResponse myRes = new MyResponse(
mySer.getDetails(),
mySer.getPicture(),
mySer.getSomethingElse()
);
These calls (getDetails, getPicture...) send requests to end point and return responses which are then just mapped into the the fields of MyResponse class constructor. This happens by the framework so MyResponse has annotations #XmlRootElement and #XmlAccessorType of type FIELD to ensure that happens.
If for whatever reason, you dont want to create response containing result of getPicture for example, you just assign null to that imput parameter.

I suggest to use #JsonProperty("") and #JsonAlias("").
class XXX {
#JsonAlias("accountName")
#JsonProperty("ACCOUNT_NAME")
private String name;
#JsonAlias("routingNumber")
#JsonProperty("ROUTING_NUMBER")
private String routing;}
I hope it helps.

Related

How to know that field is not passed

Here is an example DTO
#Getter
#Setter
public class TestDto {
private Long id;
private String name;
private String sex;
}
Say I have this object stored on the server:
{"id":1, "name": "alex", "sex": "M"}
How can I send a request that only updates the "name" portion of the object?
Perhaps I could send this:
{"id":1, "name":"adam"}
Such that the object will change to this:
{"id":1, "name": "adam", "sex": "M"}
I also need the ability to set a field to null
(i.e. clear the contents of a field).
In this case I would like to send
{"id":1, "name":"adam", "sex":null}
To have the stored DTO change to
{"id":1, "name": "adam", "sex":null}
How can I do this using java, spring boot, etc.?
I know the way to use:
#PutMapping
public TestDto update(Map<String, Object>map){ ... }
but I also need to some validation such that if I pass
{"id":"1AA" ... } I get a serialization exception.
Ps.Find first step of this magic ->
1.Before path TestDto throu Rest - need to clear Type like this
Object body = testDto;
if will help you to get an Object with field what you want on server and then you'll be able to detect list of fieds to update
Instead of attempting to detect absent vs null value,
consider defining an update object that includes a list of fields to be updated.
Such an object might look like this:
#Getter
#Setter
public class UpdateObject
{
private long id; // ID of the object to be updated.
private TestDto updates; // an object that contains the new values for the fields.
private List<String> updateFields; // a list of fields to be updated.
}
Here is some Json
{
"id": 1,
"updates":
{
"name": "blem",
"sex": null
},
"updateFields": ["name", "sex"]
}
if i understood right you just send request to the server with different fields. With #ModelAttribute annotation you can send your body in json format.
if you send only one/two field or how you want {"id":1, "name":"adam"}, due to spring data jpa you can update your model in db. (in this case your field sex will be null and you need to create some manipulation for checking it kind of Mapstruct - convert your dto in other model plus checking null/not null fields).
Better create default value for sex field if you want to saving not M and not FM values. null bad practice, in the future it will be bad joke for you.
#Getter
public Enum Sex {
private MALE,
private FEMALE,
private DEFAULT
}
Ok guys finally fount how to do this
1.Client side - > path your testDto as Object, not as TestDto.class
Object payLoad = testDto;
template.postForObject("url", payload);
2.Server side - >
#RestController
#RequestMapping("/test")
public class TestController {
private final Map<Long, TestDto> cash = new HashMap<>();
private final ObjectMapper mapper = new ObjectMapper();
#PostMapping
public TestDto create(#RequestBody TestDto dto) {
return cash.computeIfAbsent(dto.getId(), v -> dto);
}
#PutMapping("/{id}")
public TestDto update(#PathVariable Long id, #RequestBody String json) throws JsonProcessingException {
val oldValue = cash.get(id);
mapper.readerForUpdating(oldValue).readValue(json);
return cash.put(oldValue.getId(), oldValue);
}
}
this hint let you update only field that client really changed

How to return required parameters as json response from pojo class in spring boot?

what I am trying to do is,
If I take one pojo class like
#Entity
#Table(name = "property_table")
public class Property {
#Id
#Column(name = "property_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int propertyId;
#Column(name = "property_name")
private String propertyName;
#Column(name = "property_type")
private String propertyType;
}
In RestController I wrote Two Methods like
#GetMapping(value = "/getProperties", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
#ResponseBody
public List<Property> getProperties() {
//some code
}
#GetMapping(value = "/getPropertyById", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
#ResponseBody
public Property getPropertyById() {
//some code
}
So, hear what I am trying to do is
for first api method I want return json like some parameters from Property pojo class i.e., like
for getProperties api method
{
"property":[
{
"propertyId":001,
"propertyName":"PROPERTY 1"
},
{
"propertyId":002,
"propertyName":"PROPERTY 2"
}
],
In the Above json I want to return only two parameters i.e propertyId,propertyName and remaining parameter i.e propertyType I dont want to retun in json.
How to return like that?
and for the second api method I want to return all three parameters. i.e., like below
for getPropertyById api method
{
"propertyId":001,
"propertyName":"PROPERTY 1",
"propertyType:"PROPERTY_TYPE 1"
},
how to maintain different json response using same pojo class with different parameters for different api methods.
please help me to solve this isuue.
Thanks.
REST API under/over-fetching is a well-known problem. There's only two (classical ways) to handle that.
The first one is to build one model per each attribute visibility state. So, in your case, you'll need to create two different models (this kind of models are called DTO - Data Transfert Object). One model will have a propertyType attribute, the other will not. The model Property you've shared shows that you use the same class as entity and as transfert object. This solution will add some complexity to your app because you will have to implement some mappers to convert your entity to a corresponding DTO.
The second one is to accept that you send an attribute that will not be useful (be aware of the over-fetching). This solution is often the most adopted one. The cons of this solution is when you don't want to send something to your client (imagine a User model, you want to get the password from your client but you don't want to sent it back to it). Another obvious negative point is that the transactions will be larger but it is negligible in most cases
I would strongly advice you to keep your #Entity isolated in the 'db' layer. So that changes on the database side don't affect your API and vice versa. Also, you will have much better control over what data is exposed in your API. For your needs you can create 2 true DTOs, like PropertyDto and PropertyDetailsDto (or using private fields and getters/setters).
public class PropertyDto {
public String propertyId;
public String propertyName;
}
public class PropertyDetailsDto extends PropertyDto {
public String propertyType;
}
Map your #Entity to a specific dto corresponding to your needs.
EDIT
public List<PropertyDto> getProperties() {
return toPropertyDtos(repository.findAll());
}
public PropertyDetailsDto getPropertyById(Long id) {
return toPropertyDetailsDto(repository.findBy(id));
}
in some Mapper.java
...
public static List<PropertyDto> toPropertyDtos(List<Property> properties) {
return properties.stream()
.map(Mapper::toPropertyDto)
.collect(toList());
}
private static PropertyDto toPropertyDto(Property property) {
PropertyDto dto = new PropertyDto();
dto.propertyId = property.propertyId;
dto.propertyName = property.propertyName;
return dto;
}
// same stuff for `toPropertyDetailsDto`, you could extract common mapping parts in a separate private method inside `Mapper`
...

How to map json response object to a preferred format using Jackson / other library?

I am getting the below JSON response format from a third party web service:
{
"meta": {
"code": 200,
"requestId": "1"
},
"response": {
"locations": [
{
"id": "1",
"name": "XXX",
"contact": {
phone: '123',
email: 'abc'
},
"location": {
"address": [
"Finland"
]
}
},
{
// another location
}
]
}
}
And here is what I should return as a response from my own web service:
[
{
"id": "1",
"name": "XXX",
"phone": '123',
"address": "Finland"
},
{
// another location
}
]
What should I do? I've read some good stuff about Jackson but there are only a few simple examples where you map some simple JSON obj as is to POJO. In my case, I need to remove a few nodes, and also traverse deeper down the hierarchy to get the nested value. This is my baby step so far in my spring boot app:
#GET
#Path("{query}")
#Produces("application/json")
public String getVenues(#PathParam("query") String query){
return client.target(url).queryParam("query",query).request(...).get(String.class)
}
Any helps, pointers, recommendations are welcomed!
You are using JAX-RS annotations instead of the Spring web service annotations. You can make this work, but I would recommend going with the default Spring annotations because those are all autoconfigured for you if you're using the spring boot starter dependencies.
First thing - you need to create classes that are set up like the request and response. Something like this:
public class ThirdPartyResponse {
MetaData meta;
Response response;
}
public class Response {
List<Location> locations;
}
public class MetaData {
String code;
String requestId;
}
public class Location {
String id;
String name;
Contact contact;
LocationDetails location;
}
public class Contact {
String phone;
String email;
}
public class LocationDetails {
List<String> address;
}
You can use Jackson annotations to customize the deserialization, but by default it maps pretty logically to fields by name and the types you might expect (a JSON list named "locations" gets mapped to a List in your object named "locations", etc).
Next you'll want to use a #RestController annotated class for your service, which makes the service call to the third party service using RestTemplate, something like:
#RestController
public class Controller {
#Value("${url}")
String url;
#RequestMapping("/path"
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public List<Location> locations(#RequestParam String query) {
// RestTemplate will make the service call and handle the
// mapping from JSON to Java object
RestTemplate restTemplate = new RestTemplate();
ThirdPartyResponse response = restTemplate.getForObject(url, ThirdPartyResponse.class);
List<Location> myResponse = new List<>();
// ... do whatever processing you need here ...
// this response will be serialized as JSON "automatically"
return myResponse;
}
}
As you can see, Spring Boot abstracts away a lot of the JSON processing and makes it pretty painless.
Take a look at Spring's guides which are pretty helpful:
Consuming a service with RestTemplate
http://spring.io/guides/gs/consuming-rest/
Creating a web service using #RestController
https://spring.io/guides/gs/rest-service/
This can be done using google api JacksonFactory.
Below is my suggested solution for this.
First you should create a pojo class corrosponding to the json data you are recieving and the json data to which you are trying to convert.
Use google api client to map the keys to the pojo.
Below is the pojo classes corrosponding to the json data you are recieving.
import com.google.api.client.util.Key;
Class Response{
#Key("locations")
List<FromLocations> fromLocations;
}
import com.google.api.client.util.Key;
Class FromLocations
{
#Key("id")
String id;
#Key("name")
String name;
#Key("contact")
Contact contact;
#Key("location")
Location location;
}
Here Contact and Loaction will be a another classes using the same strategy;
Below is the pojo corrosponding to the json to which you want to convert.
Class ToLocations{
String id;
String name;
String phone;
String address;
}
Now you can parse the requset containing the json objec to the fromLocations class as below.
String responseMeta = response.parseAsString();
JSONObject queryJsonObject = new JSONObject(responseMeta);
if(queryJsonObject.has("locations")){
Response response = JacksonFactory.getDefaultInstance().fromString(responseMeta,Response.class);
List<FromLocations> fromLocationsList = response.getFromLocations();
}
Next step is to iterate the list fromLocationsList and get the desired values from each FromLocations object and add it to the ToLocations object.
Next the ToLocations object can be add it to a list and convert it to json.

How to add objects to JSON

In post service, I am using below method to parse and update Database:
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(<String>);
UserLogin userLogin = mapper.convertValue(node.get("UserLogin"), UserLogin.class);
UserSecurityDetails userSecurityDetails = mapper.convertValue(node.get("UserSecurityDetails"), UserSecurity
Now, In get service, I want to send the same data by retieving from DB and adding to JSON. Could anyone suggest what is the best way?
Sample JSON to be formed:
{
"UserLogin":
{
"user_login_id": "10011",
"user_password": "password"
},
"UserSecurityDetails":
{
"user_sequence_id": "1",
"seq_question_id": "1",
"seq_answer": "Test Answer"
}
}
Create a Wrapper POJO having UserLogin and UserSecurityDetails. Jackson will automatically deserialize to your object.
It will be good practice to expect required Object instead of creating objects from String.
Your Wrapper class will be like
public class SecurityDetailsWrapper {
private UserLogin;
private UserSecurityDetails;
// costructor
// getters and setters
}
in your Controller's method you can expect SecurityDetailsWrapper.
like
public void someFunction(#RequestBody SecurityDetailsWrapper wrapper) {
// business logic
}
Jackson will takes care of Deserialization.

How to get java objects from JSONArray url using Jackson in Android

This is my JSON from URL
https://api.myjson.com/bins/142jr
[
{
"serviceNo":"SR0000000001",
"serDate":"17",
"serMonth":"DEC",
"serYear":"2015",
"serTime":"02.30 AM",
"serApartmentName":"Galaxy Apartments"
},
{
"serviceNo":"SR0000000002",
"serDate":"19",
"serMonth":"JUN",
"serYear":"2016",
"serTime":"03.30 AM",
"serApartmentName":"The Great Apartments"
}
]
I have one ListView I want populate details from online JSON,above i given a link and sample json anybody given sample jackson code in java
Thanks for advance,
Rajesh Rajendiran
To use jackson you need to create a model class:
[
{
"serviceNo":"SR0000000001",
"serDate":"17",
"serMonth":"DEC",
"serYear":"2015",
"serTime":"02.30 AM",
"serApartmentName":"Galaxy Apartments"
},
{
"serviceNo":"SR0000000002",
"serDate":"19",
"serMonth":"JUN",
"serYear":"2016",
"serTime":"03.30 AM",
"serApartmentName":"The Great Apartments"
}
]
For the above the json the model class would be:
public class SomeClass {
private String serviceNo;
private String serDate;
private String serMonth;
private String serYear;
private String serTime;
private String serApartmentName;
#JsonProperty("serviceNo") //to bind it to serviceNo attribute of the json string
public String getServiceNo() {
return serviceNo;
}
public void setServiceNo(String sNo) { //#JsonProperty need not be specified again
serviceNo = sNo;
}
//create getter setters like above for all the properties.
//if you want to avoid a key-value from getting parsed use #JsonIgnore annotation
}
Now whenever you have the above json as string stored in a variable say jsonString use the following code to parse it:
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
ArrayList<SomeClass> results = mapper.readValue(jsonString,
new TypeReference<ArrayList<ResultValue>>() { } );
results should now contain two SomeClass objects having the above json parsed as respective objects.
PS: Its been a long time since I have used Jackson for parsing so this code might need some improvements.
If you are getting this as http response then I would suggest to use spring rest template for android.
It has support for Message Converters. That way the onus of marshaling and unmarshalling.
[Update]
Here is a blog for the same :http://www.journaldev.com/2552/spring-restful-web-service-example-with-json-jackson-and-client-program
Refer Docs for more details:
http://docs.spring.io/spring-android/docs/current/reference/html/rest-template.html

Categories

Resources