Json response is duplicated when using jsonAnyGetter - json

I have a class FolderResult with the following model defined. I am getting duplicate entries for uploadDetails. When i inspect the map has only one entry
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.HashMap;
import java.util.Map;
public class FolderResult {
private String folderType;
#JsonProperty("uploadDetails")
private Map<String, Object> uploadDetails = new HashMap<>();
public String getFolderType() {
return folderType;
}
public void setFolderType(String folderType) {
this.folderType = folderType;
}
#Override
public String toString() {
return "FolderResult{"
+ "folderType='"
+ folderType
+ '\''
+ ", uploadDetails="
+ uploadDetails
+ '}';
}
#JsonAnyGetter
public Map<String, Object> getUploadDetails() {
return uploadDetails;
}
#JsonAnySetter
public void setUploadDetails(String key, Object value) {
uploadDetails.putIfAbsent(key, value);
}
}
In the API Response for 201, i have defined this class as the output.
I get duplicate responses.
{
"folderType": "mri",
"uploadDetails": {
"mriLocationsFile": {
"uploadUrl": "String",
"fileUri": "import/folders/1349/files/4310",
"presignParams": {
"accessKeyId": "ff=",
"secretAccessKey": "dd==",
"sessionToken": "dd",
"path": "dd",
"region": "dd"
}
},
"mriLocationsFile": {
"uploadUrl": "String",
"fileUri": "import/folders/1349/files/4310",
"presignParams": {
"accessKeyId": "ff=",
"secretAccessKey": "dd==",
"sessionToken": "dd",
"path": "dd",
"region": "dd"
}
}
}
I would like only one uploadDetails in json like below. What should i fix in model
{
"folderType": "mri",
"uploadDetails": {
"mriLocationsFile": {
"uploadUrl": "String",
"fileUri": "import/folders/1349/files/4310",
"presignParams": {
"accessKeyId": "ff=",
"secretAccessKey": "dd==",
"sessionToken": "dd",
"path": "dd",
"region": "dd"
}
}
}

Related

Android Retrofit - Array data is empty

I want to receive Json data from server using Retrofit.
Below is Data class and Json example.
After finish transfer the 'Page' object is returned from Response.body().
But inside it the array 'cards' has 'null' value.
How can I get the correct data?
[Page.java]===========
public class Page {
public List<Cards> cards;
public Page(List<Cards> cards) {
this.cards = cards;
}
public class Cards {
public String card_type;
public Cards(String card_type) {
this.card_type = card_type;
}
}
}
[Json example]===============
{
"page": {
"cards": [
{
"card_type": "text",
"card": {
"value": "Hello, Welcome to App!",
"attributes": {
"text_color": "#262626",
"font": {
"size": 30
}
}
}
},
{
"card_type": "title_description",
"card": {
"title": {
"value": "Check out our App every week for exciting offers.",
"attributes": {
"text_color": "#262626",
"font": {
"size": 24
}
}
},
"description": {
"value": "Offers available every week!",
"attributes": {
"text_color": "#262626",
"font": {
"size": 18
}
}
}
}
},
]
}
}
first of all your model class not have get methods , your methods are setter not getter and its normal you cant get data without getter method , change your model like below :
at first , do not use inner class , made classes separate together
public class Page {
public List<cards> cards;
public List<cards> getCards() {
return cards;
}
public class cards {
public String card_type;
public String getCard_type() {
return card_type;
}
public card card;
public card getCard() {
return card;
}
}
public class card {
public String value;
public String getValue() {
return value;
}
public attributes attributes;
public String getAttributes() {
return attributes;
}
}
now this classes correct for your index 0 of cards , but your Json sample not have organization at next index ... but you can made title class or description class and add it to card class for get more data from any index of your list.

how to parse a json similar string and map it into a pojo

I am trying to map the following JSON to my POJO using Jackson. I have the following JSON and following POJOs. kindly let me know how to map the JSON to POJO.
JSON string :
{
"Application": {
"id": "0",
"name": "MyApp",
"users": [
{
"User": {
"id": "2",
"name": "Beth Jones"
}
}
],
"groups": [
{
"Group": {
"id": "1",
"name": "SimpleGroup",
"users": [
{
"User": {
"id": "2",
"name": "Beth Jones"
}
}
]
}
}
]
}
}
The POJO according to the client specification is below :
package com.example.custom;
//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.example.Application;
import com.example.Group;
import com.example.User;
import java.util.Collection;
//#JsonIgnoreProperties(ignoreUnknown = true)
public class MyApplication extends Application {
private Collection<User> users;
private Collection<Group> groups;
public MyApplication(String id, String name) {
super(id, name);
}
public void setUsers(Collection<User> users) {
this.users = users;
}
public void setGroups(Collection<Group> groups) {
this.groups = groups;
}
#Override
public Collection<User> getUsers() {
return this.users;
}
#Override
public User getUser(String userId) {
for (User user: MyParser.myApp.getUsers()) {
if (user.getId().equals(userId))
return user;
}
return null;
}
#Override
public Collection<Group> getGroups() {
return this.groups;
}
#Override
public Group getGroup(String groupId) {
for (Group group: MyParser.myApp.getGroups()) {
if (group.getId().equals(groupId))
return group;
}
return null;
}
#Override
public String toString() {
return "MyApplication{" +
"users=" + users +
", groups=" + groups +
'}';
}
}
Mapping Logic :
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyParser.myApp = mapper.readValue(rewriter.getText(),MyApplication.class);
The resulting object is not able to capture anything as it is all null. Kindly help. Thanks in advance.
I think you should model your JSON correctly, In the users list you shouldn't specify it again that the key is User, that should be preassumed that a list of users will only contain user, same goes for groups list.
IMHO the JSON should look something like this :
{
"application": {
"id": "0",
"name": "MyApp",
"users": [ . ==> Since this is a user List, it will definitely contains user.
{
"id": "2",
"name": "Beth Jones"
}
],
"groups": [
{
"id": "1",
"name": "SimpleGroup",
"users": [
{
"id": "2",
"name": "Beth Jones"
}
]
}
]
}
}
Now the POJO also needs some modification, I am just adding the bare-minimum POJO.
class Application { <====== Top Level Class
private Long id;
private String name;
private List<User> users; // Application has some Users
private List<Group> groups; // Application has some groups
}
class User {
private Long id;
private String name;
}
class Group {
private Long id;
private String name;
private List<User> users; // Each group has some associated users.
}
Now you can use any standard JSON library for Java and convert your JSON into POJO. This will simplify your structure and you won't face null issues with this structure.

Marhall/unmarshall JSON with array as a top-level element

I need to unmarshall JSON having array as a top-level element:
[
{
"test1":
{
"name": "Boost",
"fraction": 0.55
}
},
{
"test2":
{
"name": "Boost",
"fraction": 0.55
}
}
]
My top-level element looks like this:
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
public class Wrapper<T> {
#XmlTransient
private List<T> items;
public Wrapper() {
items = new ArrayList<>();
}
public Wrapper(List<T> items) {
this.items = items;
}
#XmlElement
public List<T> getItems() {
return items;
}
}
Unmarshalling is done in this method:
private <T> T get(String path, Class<T> aClass) {
WebTarget target = root.path(path);
Invocation.Builder request = target.request(MediaType.APPLICATION_JSON_TYPE);
return request.get(aClass);
}
When I tried to marshall an existing object into json I have got the following result:
{
"items" : [
{
"test1":
{
"name": "Boost",
"fraction": 0.55
}
},
{
"test2":
{
"name": "Boost",
"fraction": 0.55
}
}
]}
How can I force JAXB to skip this items key?
Thanks for your help.
I solved the problem using GenericType new GenericType<List<MyObject>>() {}

Jackson: JSON parsing for array of parent elements : Root name '' does not match expected ('List')

I am getting the following exception after writing the below code.
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Root name 'Filing' does not match expected ('List') for type [collection type; class java.util.List, contains [simple type, class MasMonthlyReportDetail]]
JSON Object
{
"Filing":
[
{
"periodInfo":
{
"date": "06-05-2013",
"year": "2015",
"Month": "January"
},
"employerInfo":
{
"name": "Y",
"place": "Y",
"country": "N",
},
"employeeInfo":
[
{
"name": "785-23-0370",
"dob": "05/25/1952",
}
],
"messages":
[
{
"defaultMessage" : "xx",
"messageType" : "yy",
"messageCode" : "102"
}
]
},
{
"periodInfo":
{
"date": "06-05-2013",
"year": "2015",
"Month": "January"
},
"employerInfo":
{
"name": "Y",
"place": "Y",
"country": "N",
},
"employeeInfo":
[
{
"name": "785-23-0370",
"dob": "05/25/1952",
}
],
"messages":
[
{
"defaultMessage" : "xx",
"messageType" : "yy",
"messageCode" : "102"
}
]
}
]
}
Main Class
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
List<MasMonthlyReportDetail> lcd = objectMapper.readValue(new File(filePath),new TypeReference<List<MasMonthlyReportDetail>>(){});
MasMonthlyReportDetail.java
#JsonRootName(value="Filing")
public class MasMonthlyReportDetail {
private PeriodInfo periodInfo;
private EmployerInfo employerInfo;
List<EmployeeInfo> employeeInfo;
List<Messages> messages;
public PeriodInfo getPeriodInfo() {
return periodInfo;
}
public void setPeriodInfo(PeriodInfo periodInfo) {
this.periodInfo = periodInfo;
}
public EmployerInfo getEmployerInfo() {
return employerInfo;
}
public void setEmployerInfo(EmployerInfo employerInfo) {
this.employerInfo = employerInfo;
}
public List<EmployeeInfo> getEmployeeInfo() {
return employeeInfo;
}
public void setEmployeeInfo(List<EmployeeInfo> employeeInfo) {
this.employeeInfo = employeeInfo;
}
public List<Messages> getMessages() {
return messages;
}
public void setMessages(List<Messages> messages) {
this.messages = messages;
}
}
I made the following changes and the code worked for me.
Main Class:
InputStream inputStream = resource.getInputStream();
ObjectMapper objectMapper = new ObjectMapper();
MasMonthlyReportDetailHolder masMonthlyReportDetailHolder = objectMapper.readValue(inputStream, MasMonthlyReportDetailHolder.class);
List<MasMonthlyReportDetail> masMonthlyReportDetail = masMonthlyReportDetailHolder.getMasMonthlyReportDetail();
MasMonthlyReportDetailHolder class:
public class MasMonthlyReportDetailHolder {
private List<MasMonthlyReportDetail> masMonthlyReportDetail;
#JsonProperty("Filing")
public List<MasMonthlyReportDetail> getMasMonthlyReportDetail() {
return masMonthlyReportDetail;
}
public void setMasMonthlyReportDetail(
List<MasMonthlyReportDetail> masMonthlyReportDetail) {
this.masMonthlyReportDetail = masMonthlyReportDetail;
}
}
Adding #JsonProperty("Filing") is the key to avoid this issue. In case of any other procedure, do let me know.
have u tried this ?
jacksonObjectMapper.reader(MasMonthlyReportDetail.class).withRootName("Filing").readValue(jsonAsString);

How to achieve same output after migrating from jackson to gson as json processor?

I am developing a restful webservices using resteasy. Earlier, the provider was jackson.
And the result output is
[
{
"status": {
"id": 22,
"name": "VERIFY",
"note": ""
}
},
{
"status": {
"id": 23,
"name": "ACCEPTED",
"note": ""
}
},
{
"status": {
"id": 24,
"name": "POSTPONED",
"note": "for cancel update"
}
},
{
"status": {
"id": 29,
"name": "AMC(NEW)"
}
},
{
"status": {
"id": 30,
"name": "AMC(ASSIGNED)"
}
}
]
Later, we moved to gson as provider. http://eclipsesource.com/blogs/2012/11/02/integrating-gson-into-a-jax-rs-based-application/
The output change as :
[
{
"id": 0,
"name": "DISABLE"
},
{
"id": 1,
"name": "ENABLE"
},
{
"id": 31,
"name": "REJECTED",
"note": ""
},
{
"id": 25,
"name": "ASSIGNED"
}
]
The class definition
package com.apt.common.web.pojo;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Status {
Integer id;
String name;
private String note;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString(){
return name;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Status other = (Status) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
Output is totally different.
Using jackson
{
"status": {
"id": 22,
"name": "VERIFY",
"note": ""
}
}
using gson
{
"id": 0,
"name": "DISABLE"
}
Code for generating json using gson is
Gson gson=new Gson();
Type fooType = new TypeToken<List<Status>>() {}.getType();
return gson.toJson(statuses,fooType);
How can i achieve the same output using gson?
I guess that in order to achieve the same result using Gson, you'll need another class to wrap your Status class, with an attribute called status, because what Gson includes in the serialized JSON are the names of the attributes, not the names of the classes!
So you'll need something like:
public class MyClass {
private Status status;
//...
}
And then in the serialization:
//...
Type fooType = new TypeToken<List<MyClass>>() {}.getType();
//...
In other words, for Gson, this JSON piece:
{
"status": {
"id": 22,
"name": "VERIFY",
"note": ""
}
}
represents this class structure:
class MyClass
Status status;
class Status
int id;
String name;
String note;
If you don't want to create another class, you can always write a custom serializer for your Status class...