Rest response bean extends Map - java

In a spring rest application context, i'm trying to create a generic response bean.
The purpose is to avoid to create a specific bean for each method.
I'd like to use standard fields, like status and message, by binding various properties to a map.
Consider the following example :
public class ResponseRestDefault extends HashMap {
private String status;
private String message;
public ResponseRestDefault() {
}
public void addParam(String key, String value) {
this.put(key, value);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Usage
#RequestMapping(value = "response", method = RequestMethod.GET)
public ResponseEntity<ResponseRestDefault> response() {
ResponseRestDefault response = new ResponseRestDefault();
response.setStatus("success");
response.setMessage("ok");
response.addParam("test", "value");
return ResponseEntity.ok(response);
}
Json result :
{
"test": "value"
}
Does the json result could contain map fields and class properties ?

You need to modify your response class. Make sure you have the getter and setter methods for map.
public class ResponseRestDefault {
private String status;
private String message;
private Map<String, String> map = new HashMap<>();
public ResponseRestDefault() {
}
public void setMap(String key, String value) {
map.put(key, value);
}
public Map<String, String> getMap()
{
return map;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
You will get response in below format :
{
"status": "success",
"message": "ok",
"map": {
"test": "value"
}
}

Related

How to handle different JSON response types on a certain field?

I'm consuming a REST API that can answer in this manner:
[
{
"status":"1",
"report":{
"name":"John",
"job":"Software Developer"
}
},
{
"status":"0",
"report":"John not found"
}
]
As you can see above the value of report field can be both a JSON Object and a String. This is the reason why I am in trouble parsing it as POJO.
For instance I have my OutcomeResponse POJO:
public class OutcomeResponse {
private String status;
private Report report;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Report getReport() {
return report;
}
public void setReport(Report report) {
this.report = report;
}
}
Where Report is:
public class Report {
private String name;
private String job;
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;
}
}
Now I'm executing a POST as follow:
OutcomeResponse [] response = client.executePost(endpoint, headers, body, OutcomeResponse [].class);
But I have an exception: I have a string in report instead of an Object as expected:
Expected BEGIN_OBJECT but was STRING at line 1 column 25 path $[0].value
How can I solve this problem?

Including nested objects in the JSON of a Spring Boot application

Can anyone guide me on how to nest the JSON object Activation under the JSON object Data.
See my JSON below:
{
"status": "Success",
"DATA": {
"aid": "0",
"app": "OASIS_EDGE",
"actkey": "STAR2020",
"expiredate": "2025-08-05 04:40:28.0",
"partner": "X",
"nsp": "NAD"
}
}
The JSON I actually expect:
{
"STATUS": "SUCCESS",
"DATA": {
"ACTIVATION": {
"aid": "0",
"app": "OASIS_EDGE",
"actkey": "STAR2020",
"expiredate": "2025-08-05 04:40:28.0",
"partner": "X",
"nsp": "NAD"
}
}
}
Here is my ActivationResponse.java class responsible for creating the JSON:
public class ActivationResponse {
private String Status;
public String getStatus()
{
return Status;
}
public void setStatus(String Status) {
this.Status = Status;
}
#JsonProperty("DATA")
private ActivationModel activationData;
public ActivationModel getActivationData() {
return activationData;
}
public void setActivationData(ActivationModel activationData2) {
this.activationData = activationData2;
}
}
Since you want activation under data, you need a class data with a field for activation, like the example below.
class MyJson {
private String Status;
#JsonProperty("DATA")
private DataModel data;
};
class DataModel {
#JsonProperty("ACTIVATION")
private ActivationModel activation;
};
Use JsonNode from com.fasterxml.jackson.databind.JsonNode à la:
import com.fasterxml.jackson.databind.JsonNode;
public class ActivationResponse {
private String Status;
private JsonNode activationData;
public String getStatus() return Status;
public void setStatus(String Status) this.Status = Status;
public ActivationModel getActivationData() return activationData;
public void setActivationData(ActivationModel activationData2) {
activationData = activationData2;
}
}
Use the good 'ol Map from java.util.Map like so:
import java.util.Map;
public class ActivationResponse {
private String Status;
private Map<String, Object> activationData;
public String getStatus() return Status;
public void setStatus(String Status) this.Status = Status;
public ActivationModel getActivationData() return activationData;
public void setActivationData(ActivationModel activationData2) {
activationData = activationData2;
}
}
I shamelessly borrowed from this tutorial (no affiliations)!

how to deserialize nested objects in java using object mapper

I have a sqs queue , I am polling for messages .
I get the message in following format
{
"Type" : "type_value",
"MessageId" : "message_id",
"TopicArn" : "topic_arn",
"Message" : "{\n \"contentType\": \"content_type_value\",\n \"content\": \"content_value\",\n \"eventName\": \"event_name\",\n \"eventTS\": 1591235390353\n}",
"Timestamp" : "2020-06-04T01:49:50.358Z",
"SignatureVersion" : "1",
"UnsubscribeURL" : "url"
}
when I get this body from SQS using code
String message = sqs_message_object.getBody()
Now I create a wrapper class for thie message body as following
public class SQSMessage
{
#JsonProperty("Type")
private String type;
#JsonProperty("MessageId")
private String messageId;
#JsonProperty("TopicArn")
private String topicArn;
#JsonProperty("Message")
private Message message;
#JsonProperty("Timestamp")
private String timestamp;
#JsonProperty("SignatureVersion")
private int signatureVersion;
#JsonProperty("UnsubscribeURL")
private String unSubscribeUrl;
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getMessageId()
{
return messageId;
}
public void setMessageId(String messageId)
{
this.messageId = messageId;
}
public String getTopicArn()
{
return topicArn;
}
public void setTopicArn(String topicArn)
{
this.topicArn = topicArn;
}
public Message getMessage()
{
return message;
}
public void setMessage(Message message)
{
this.message = message;
}
public String getTimestamp()
{
return timestamp;
}
public void setTimestamp(String timestamp)
{
this.timestamp = timestamp;
}
public int getSignatureVersion()
{
return signatureVersion;
}
public void setSignatureVersion(int signatureVersion)
{
this.signatureVersion = signatureVersion;
}
public String getUnSubscribeUrl()
{
return unSubscribeUrl;
}
public void setUnSubscribeUrl(String unSubscribeUrl)
{
this.unSubscribeUrl = unSubscribeUrl;
}
}
And I deserialize the json string in to a SQSMessage object using Object Mapper
SQSMessage sqsMessage = null;
try
{
sqsMessage = objectMapper.readValue(message,SQSMessage.class);
}
catch(JsonProcessingException e2)
{
}
all the fields are getting mapped except for Message field .
because its not just a string but another class.
public class Message
{
private String contentType;
private Content content;
private String eventName;
private Date eventTS;
public String getContentType()
{
return contentType;
}
public void setContentType(String contentType)
{
this.contentType = contentType;
}
public Content getContent()
{
return content;
}
public void setContent(Content content)
{
this.content = content;
}
public String getEventName()
{
return eventName;
}
public void setEventName(String eventName)
{
this.eventName = eventName;
}
public Date getEventTS()
{
return eventTS;
}
public void setEventTS(Date eventTS)
{
this.eventTS = eventTS;
}
}
it fils to deserialize the field Message .
how do i Map the message field to Messaeg class as mentioned.
The error I get is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `domain.Message`
(although at least one Creator exists): no String-argument constructor/factory method to deserialize
from String value ('{\n \"contentType\": \"content_type_value\",\n \"content\": \"content_value\",\n \"eventName\": \"event_name\",\n \"eventTS\": 1591235390353\n}')
at [Source: (String)"{

Json Parsing and assign to DTO using Jackson

Facing some issue while parsing JSON into DTO.
In Json Getting Response as below
{
"errorMsg": null,
"flag": "S",
"message": "",
"coi_Number": "1234567",
"expiryDate": "7/12/2019 12:00:00 AM"
}
In DTO :
#JsonProperty("errorMsg")
private Object errorMsg;
#JsonProperty("flag")
private String flag;
#JsonProperty("message")
private String message;
#JsonProperty("coi_Number")
private String coiNumber;
#JsonProperty("expiryDate")
private String expiryDate;
#JsonProperty("errorMsg")
public Object getErrorMsg() {
return errorMsg;
}
#JsonProperty("errorMsg")
public void setErrorMsg(Object errorMsg) {
this.errorMsg = errorMsg;
}
#JsonProperty("flag")
public String getFlag() {
return flag;
}
#JsonProperty("flag")
public void setFlag(String flag) {
this.flag = flag;
}
#JsonProperty("message")
public String getMessage() {
return message;
}
#JsonProperty("message")
public void setMessage(String message) {
this.message = message;
}
#JsonProperty("coi_Number")
public String getCoiNumber() {
return coiNumber;
}
#JsonProperty("coi_Number")
public void setCoiNumber(String coiNumber) {
this.coiNumber = coiNumber;
}
#JsonProperty("expiryDate")
public String getExpiryDate() {
return expiryDate;
}
#JsonProperty("expiryDate")
public void setExpiryDate(String expiryDate) {
this.expiryDate = expiryDate;
}
Getting value as null. Please suggest what is the way to resolve it using Spring MVC.
In response getting value but after setting value in DTO getting coiNumber as null.
Try changing private String coiNumber to coi_Number
In response, you are getting key as "coi_Number" but in the entity, you are using this.
Solution 1:
#JsonProperty("coi_Number")
private String coiNumber;
Try changing the above to
#JsonProperty("coi_Number")
private String coi_Number
Solution 2:
If the above solution 1 doesn't work then try changing
#JsonProperty("coi_Number")
to
#JsonProperty("coi_number")

Retrofit/Jackson error on deserializing

i'm trying to get a JSON from my web service and deserialize to my class UserSync, but i'm getting the following error:
Can not instantiate value of type [simple type, class com.example.breno.teste.model.User] from String value (''); no single-String constructor/factory method
at [Source: okhttp3.ResponseBody$BomAwareReader#fbf814f; line: 1, column: 86] (through reference chain: com.example.breno.teste.dto.UserSync["user"])
I've read some posts saying that i need to declare my User class static in UserSync, but when i do that, jackson can't find any user property, even with JsonDescription. Another posts say that i may need to declare a default constructor, so i did.
Here is the UserSync class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class UserSync {
#JsonProperty("status")
private String Status;
#JsonProperty("currentDate")
private String CurrentDate;
#JsonProperty("message")
private String Message;
#JsonProperty("user")
private static User NewUser;
public UserSync() {
}
public String getStatus() {
return Status;
}
public String getCurrentDate() {
return CurrentDate;
}
public String getMessage() {
return Message;
}
public static User getNewUser() {
return NewUser;
}
The User class:
public class User implements Serializable {
#JsonProperty("userKey")
private UUID UserKey;
#JsonProperty("userPassword")
private String UserPassword;
#JsonProperty("userGroupKey")
private UUID UserGroupKey;
#JsonProperty("signInDate")
private String SignInDate;
#JsonProperty("active")
private boolean Active;
#JsonProperty("profilePicturePath")
private String ProfilePic;
#JsonProperty("completeName")
private String UserCompleteName;
#JsonProperty("email")
private String UserEmail;
#JsonProperty("isLogged")
private boolean IsLogged;
public User() {
}
public boolean getIsLogged() {
return IsLogged;
}
public void setIsLogged(boolean isLogged) {
IsLogged = isLogged;
}
public String getUserEmail() {
return UserEmail;
}
public void setUserEmail(String userEmail) {
UserEmail = userEmail;
}
public UUID getUserKey() {
return UserKey;
}
public void setUserKey(UUID userKey) {
UserKey = userKey;
}
public String getUserPassword() {
return UserPassword;
}
public void setUserPassword(String userPassword) {
UserPassword = userPassword;
}
public UUID getUserGroupKey() {
return UserGroupKey;
}
public void setUserGroupKey(UUID userGroupKey) {
UserGroupKey = userGroupKey;
}
public String getSignInDate() {
return SignInDate;
}
public void setSignInDate(String signInDate) {
SignInDate = signInDate;
}
public boolean getActive() {
return Active;
}
public void setActive(boolean active) {
Active = active;
}
public String getProfilePic() {
return ProfilePic;
}
public void setProfilePic(String profilePic) {
ProfilePic = profilePic;
}
public String getUserCompleteName() {
return UserCompleteName;
}
public void setUserCompleteName(String userCompleteName) {
UserCompleteName = userCompleteName;
}
}
My service class (Using now the postNewUser):
public interface UserService {
#GET("Login/LoginUser?")
Call<UserSync> login(#Query("email") String email, #Query("password") String password);
//region NewUser Services
#GET("Login/VerifyNewUser?")
Call<UserSync> validateNewUser(#Query("email") String email);
#POST("Login/PostNewUser")
Call<UserSync> postNewUser(#Body User user);
//endregion
}
And finally, the JSON:
{
"status": "OK",
"currentDate": "20/07/2017 11:59:02",
"message": "teste",
"user": {
"userKey": "8e2f0d2d-3522-472d-be1d-28791367f4ee",
"email": "teste_teste#hotmail.com",
"userPassword": "123456",
"profilePicturePath": "teste",
"completeName": "Jorge",
"userGroupKey": null,
"signInDate": "2017-07-07T16:26:06.097",
"active": true,
"isLogged": true
}
}
Can someone help me, please?
EDIT 1 - Here is the method that i'm using to do the retrofit call:
public void register(User user) {
Call<UserSync> postCall = new RetrofitInitializator().getUserService().postNewUser(user);
postCall.enqueue(getRegisterCallback());
}
#NonNull
private Callback<UserSync> getRegisterCallback() {
return new Callback<UserSync>() {
#Override
public void onResponse(Call<UserSync> call, Response<UserSync> response) {
User user = response.body().getNewUser();
}
#Override
public void onFailure(Call<UserSync> call, Throwable t) {
Log.e("Register - onFailure", t.getMessage());
}
};
}
EDIT 2 - The retrofitInicializator class:
public class RetrofitInitializator {
private final Retrofit retrofit;
public RetrofitInitializator() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient
.Builder();
builder.addInterceptor(interceptor);
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.15.6:7071/api/")
.addConverterFactory(JacksonConverterFactory.create())
.client(builder.build())
.build();
}
public UserService getUserService() {
return retrofit.create(UserService.class);
}
}
I managed to resolve my problem switching the type User to JsonNode and doing the convertion after this.
#JsonProperty("status")
private String Status;
#JsonProperty("currentDate")
private String CurrentDate;
#JsonProperty("message")
private String Message;
#JsonProperty("user")
private JsonNode NewUser;
and the convertion:
private User getUserFromUserAsync(UserSync userSync) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.treeToValue(userSync.getNewUser(), User.class);
}

Categories

Resources