I am mapping an object to JSON and have a problem with one variable called Parameters of type List <SimilarityParameter>.
SimilarityParameter looks like this:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class SimilarityParameter {
private String name;
private String type;
public SimilarityParameter() {
}
public SimilarityParameter(String name, String type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
When this List is large everything is OK. The JSON looks like this
{
"parameters":[
{
"name":"threshold",
"type":"Double"
},
{
"name":"numberOfResults",
"type":"Integer"
}
]
}
This is OK because after JSON encoding on the client side I have an array of Parameters.
The problem is when List is of size 1. Mapper transfers it logically to:
{
"parameters":{
"name":"numberOfResults",
"type":"Integer"
}
}
When the client decodes this JSON gets gets an array containing name and type. It causes inconsistencies on the client side.
I would like to map List of size 1 to this:
{
"parameters":[
{
"name":"threshold",
"type":"Double"
}
]
}
So after encoding array containing one parameter.
This is how the response looks:
#XmlRootElement(name = "availableSimilarities")
#XmlAccessorType(XmlAccessType.FIELD)
public class SimilarityInfoResult {
private String similarityName;
private List <SimilarityParameter> parameters;
public SimilarityInfoResult() {
}
public SimilarityInfoResult(String similarityName, List<SimilarityParameter> parameters) {
this.similarityName = similarityName;
this.parameters = parameters;
}
public String getName() {
return similarityName;
}
public void setName(String similarityName) {
this.similarityName = similarityName;
}
public List<SimilarityParameter> getParameters() {
return parameters;
}
public void setParameters(List<SimilarityParameter> parameters) {
this.parameters = parameters;
}
}
Is it possible to achieve this?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The problem is when List is of size 1. Mapper transfers it logically
to:
The JAXB specification itself does not cover JSON-binding so sometimes implementations are used with libraries like Jettison which converts XML events to/from JSON and problems occur such as collections of size 1 being represented incorrectly. This is because Jettison (and similar) libraries can only detect collections when they see an element appear more than once.
http://blog.bdoughan.com/2011/04/jaxb-and-json-via-jettison.html
Is it possible to achieve this?
The EclipseLink MOXy implementation of JAXB offers native JSON binding meaning that items like collections of size 1 will be properly converted to JSON.
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properites in the same package as your domain model with the following entry:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(2);
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {SimilarityInfoResult.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource json = new StreamSource("src/forum15316288/input.json");
SimilarityInfoResult result = unmarshaller.unmarshal(json, SimilarityInfoResult.class).getValue();
Marshaller marshaller= jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(result, System.out);
}
}
input.json/Output
{
"parameters" : [ {
"name" : "threshold",
"type" : "Double"
} ]
}
For More Information
http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html
Related
In Apache Johnzon, is there a way to hava a generic field that contains dynamic JSON data, not mappable to a pre-defined POJO?
In Jackson you can simply use ObjectNode as a generic container, have some JSON processing on it, and then write the whole object in JSON format.
In Jackson it works as expected using ObjectNode, here is my code:
public class JsonTest {
private String myStaticKey = "foo";
private ObjectNode jsonData;
//code to initialize ObjectNode + getters + setters
#JsonIgnore
public void addValue(String key, String value) {
jsonData.put(key, value);
}
#JsonIgnore
public String toJson() {
return new ObjectMapper().writeValueAsString(this);
}
}
public class MainTest {
public static void main(String[] args) {
JsonTest t = new JsonTest();
t.addValue("myDynamicKey", "bar");
System.out.println(t.toJson());
}
}
Expected result:
{
"myStaticKey": "foo",
"jsonData": {
"myDynamicKey": "bar"
}
}
I have a JAX-RS REST endpoint of PUT type and I am supposed to pass a Map to this API.
#PUT
#Path("/some/path")
#Consumes({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML,
MediaType.TEXT_XML, MediaType.APPLICATION_JSON })
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response updatePerson(HashMap<Person, Person> map) {
//some code here
}
I generated JSON for Person class but I am not able to pass it as a JSON input to this API. I am using Postman client and it says Syntax error while I try to pass the JSON input as key value pair. JSON generated for Person looks something like below
{"name":"abc","weight":100.0,"id":"123"}
I need to pass this as key value pair as a map. Something like
{
{"name":"abc","weight":100.0,"id":"123"} :
{"name":"def","weight":200.0,"id":"123"}
}
Any pointers how do I do this?
Generally it looks like a bad idea to create Map like this. JSON Object can be converted to Java Map where key is String and value is any Object: can be another Map, array, POJO or simple types. So, generally your JSON should look like:
{
"key" : { .. complex nested object .. }
}
Theres is no other option. If you want to have in Java mapping POJO -> POJO you need to instruct deserialiser how to convert JSON-String-key to an object. There is no other option. I will try to explain this process using Jackson library because it is most used in RESTful Web Services. Let's define Person class which fits to your JSON payload.
class Person {
private String name;
private double weight;
private int id;
public Person() {
}
public Person(String value) {
String[] values = value.split(",");
name = values[0];
weight = Double.valueOf(values[1]);
id = Integer.valueOf(values[2]);
}
public Person(String name, double weight, int id) {
this.name = name;
this.weight = weight;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id;
}
#Override
public int hashCode() {
return Objects.hash(id);
}
#Override
public String toString() {
return name + "," + weight + "," + id;
}
}
Because it is used in Map as key we need to implement hashCode and equals methods. Except public Person(String value) constructor and toString method everything else looks pretty normal. Now, let's take a look on this constructor and toString method. They are in correlation: toString builds String from the Person instance and constructor builds Person from String. We can call first transformation as serialisation and second as deserialisation of our key in Map serialisation and deserialisation. (Whether these two are well implemented this is another story. I just want to show an idea behind it. Before using on production should be improved)
Let's use this knowledge and Jackson features to serialise and deserialise Map<Person, Person>:
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.MapType;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class JsonApp {
public static void main(String[] args) throws Exception {
// register deserializer for Person as keys.
SimpleModule module = new SimpleModule();
module.addKeyDeserializer(Person.class, new PersonKeyDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// Create example Map
Person key = new Person("Rick", 80.5, 1);
Person value = new Person("Morty", 40.1, 2);
Map<Person, Person> personMap = new HashMap<>();
personMap.put(key, value);
// Serialise Map to JSON
String json = mapper.writeValueAsString(personMap);
System.out.println(json);
// Deserialise it back to `Object`
MapType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, Person.class, Person.class);
System.out.println(mapper.readValue(json, mapType).toString());
}
}
class PersonKeyDeserializer extends KeyDeserializer {
#Override
public Object deserializeKey(String key, DeserializationContext ctxt) {
return new Person(key);
}
}
Above code prints as first JSON:
{
"Rick,80.5,1" : {
"name" : "Morty",
"weight" : 40.1,
"id" : 2
}
}
As you can see, Person's toString method was used to generate JSON key. Normal serialisation proces serialised Person to JSON object. As second below text is printed:
{Rick,80.5,1=Morty,40.1,2}
This is a default representation of Map and it's keys and values. Because both are Person object it's toString method is invoked.
As you can see there is an option to send JSON as Map<Person, Person> but key should be somehow represented. You need to take a look on Person class implementation. Maybe you will find some similarities to my example. If no, maybe it was configured somehow. First of all try to send in PostMan:
{
"123" : {"name":"def","weight":200.0,"id":"123"}
}
Or:
{
"{\"name\":\"abc\",\"weight\":100.0,\"id\":\"123\"}":{
"name":"def",
"weight":200.0,
"id":"123"
}
}
Maybe it will work.
See also:
Map Serialization and Deserialization with Jackson
Custom ObjectMapper with Jersey 2.2 and Jackson 2.1
JBoss resteasy - Custom Jackson provider
I am trying to generate the following using fasterxml jackson.. but I am stuck. I can't seem to work out how to create arrays.
{
"setAccId":"12345",
"groupOf":null,
"isEnabled":false,
"list":[
{
"student":"jim",
"type":"S_A",
"retro":null
},
{
"student":"bob",
"type":"S_A",
"retro":null
}
],
"sort":[]
}
I have two classes. One has the Json properties, and the other is where I print it.
Below class (DynamicJsonHelper) is where I have all the json properties
package com.company.jsonfc;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonPropertyOrder({
"accId",
"groupOf",
"isEnabled"
})
public class DynamicJsonHelper {
public String accId;
public String groupOf;
public List studentList;
#JsonProperty("accId")
public void setAccId(String accId) {
this.accId = accId;
}
#JsonProperty("groupOf")
public void setGroupOf(String groupOf) {
this.groupOf = groupOf;
}
#JsonProperty("isEnabled")
public boolean isEnabled() {
return false;
}
#JsonProperty("studentList")
public List<StudentList> studentList() {
return studentList;
}
}
Student List Class (as suggested)
class StudentList {
String student;
String type;
String retro;
}
And here is class (PrintJson) where I call it.
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.company.jsonfc.DynamicJsonHelper;
#JsonInclude(JsonInclude.Include.NON_NULL)
public class PrintJson {
#Test
public void create_json() throws JsonProcessingException {
final JsonNodeFactory factory = JsonNodeFactory.instance;
DynamicJsonHelper dynamicJsonHelper = new DynamicJsonHelper();
String jsonString;
ObjectMapper mapper = new ObjectMapper();
dynamicJsonHelper.setAccId("12345");
jsonString = mapper.writeValueAsString(dynamicJsonHelper);
System.out.println(jsonString);
}
}
This results in printing the following:
{
"setAccId":"12345",
"groupOf":null,
"isEnabled":false
"studentList":null
}
1) How do I add the list:[ ... ] array & the sort: [ ] at the end too?
2) In class PrintJson, I don't set value for groupOf but it is still created in Json. How do I set it so if I set value, it is printed.. otherwise it is not included in the json being printed.
I would appreciate if you took my code and gave me example based on it for better understanding please
1) How do I add the list:[ ... ] array & the sort: [ ] at the end too?
Answer: You can create two more classes one for list and one for sort. Now in the class DynamicJsonHelper you can add both of them like you have added accId or isEnabled
and they will be printed. Make sure to add the fields you want in them as instance variables in both of the classes. For example for list you can have a class like:
class StudentList{
String student;
String type;
String retro;
}
Now add a field in your class DynamicJsonHelper as List<StudentList>. Similarly you can do for sort.
2) In class PrintJson, I don't set value for groupOf but it is still
created in Json. How do I set it so if I set value, it is printed..
otherwise it is not included in the json being printed.
Answer: You can either use Object mapper and set it to ignore the null fields during serialization. For eg: mapper.setSerializationInclusion(Include.NON_NULL);
Or you can set it at class level to ignore null values if any. For eg:
#JsonInclude(Include.NON_NULL)
class Test
{
String t;
}
As mentioned in the comments by aBnormaLz above doesn't work if the type is primitive like you have for isEnabled. So consider changing it to Boolean and ensure the same for other fields also.
Edit:
#JsonPropertyOrder({
"accId",
"groupOf",
"isEnabled"
})
#JsonInclude(JsonInclude.Include.NON_NULL)
public class DynamicJsonHelper {
public String accId;
public String groupOf;
public List<Student> studentList;
#JsonProperty("accId")
public void setAccId(String accId) {
this.accId = accId;
}
#JsonProperty("groupOf")
public void setGroupOf(String groupOf) {
this.groupOf = groupOf;
}
#JsonProperty("isEnabled")
public boolean isEnabled() {
return false;
}
#JsonProperty("studentList")
public void setStudentList(List<Student> list) {
this.studentList = list;
}
}
class Student {
private String student;
private String type;
private String retro;
public Student(String student, String type, String retro) {
this.student = student;
this.type = type;
this.retro = retro;
}
public String getStudent() {
return student;
}
public void setStudent(String student) {
this.student = student;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRetro() {
return retro;
}
public void setRetro(String retro) {
this.retro = retro;
}
}
class HelperTest{
public static void main(String[] args) throws JsonProcessingException {
DynamicJsonHelper dynamicJsonHelper = new DynamicJsonHelper();
String jsonString;
ObjectMapper mapper = new ObjectMapper();
dynamicJsonHelper.setAccId("12345");
List<Student> list = Arrays.asList(new Student("s1", "t1", "r1"), new Student("s2", "t2", "r2"));
dynamicJsonHelper.setStudentList(list);
jsonString = mapper.writeValueAsString(dynamicJsonHelper);
System.out.println(jsonString);
}
}
After executing the program the output is as shown below:
{
"accId": "12345",
"isEnabled": false,
"studentList": [
{
"student": "s1",
"type": "t1",
"retro": "r1"
},
{
"student": "s2",
"type": "t2",
"retro": "r2"
}
]
}
You missed a point that you have to have third class and it must have property of type java.util.List or array and name list for your example.
e.g.
public class JsonHolder {
// appropriate Json/Jackson annotations ommitted
private String setAccId;
private String groupOf;
private boolean isEnabled;
private List<DynamicJsonHelper> list;
private String[] sort;
// .. getter/setters ...
}
then you have to create that object and when you created your DynamicJsonHelper put it into list or array.
After all you can serialize JsonHolder object and you will see your java List or Array as JSON array.
UPD: just note that in JSON structure like { ... } is an object and in Java there must be a class for it.
So, starting with JSON structure you posted
{
"setAccId":"12345",
"groupOf":null,
"isEnabled":false,
"list":[
{
"student":"jim",
"type":"S_A",
"retro":null
},
{
"student":"bob",
"type":"S_A",
"retro":null
}
],
"sort":[]
}
it is an object (let name it JsonHolder) with properties named setAcctId, groupOf, isEnabled, list, sort
So you have to have a Java class for it (similar as you did for your DynamicJsonHelper. You can use any #Json annotations you'd like to the same way (I omitted them and left for you). Even you will not have them Jackson or any other JSON serialiser will use property names in Java class by as default.
I mean as example your #JsonProperty("accId")
#JsonProperty("accId")
public void setAccId(String accId)
is not required as long as getter/setter/property named also getAcctId, setAcctId, acctId. Jackson will use that if there is no #JsonProperty annotation.
BTW it is better to do it as you did for code readability. :-)
Per your question:
list and sort properties in JSON are arrays. Jackson parses Java collections classes like List, Set or Arrays to JSON arrays.
Then according to required JSON structure list property is a such collection of DynamicJsonHelper objects you created. in Java class, List or Array is just your choice - use what is more suitable for you. I recommend to use a List rather than Array. Work with arrays in Java is not a good idea. :-)
So far you just created a Java class DynamicJsonHelper only for objects which must be in list property of JsonHolder object. What's left is to create that "JsonHolder" class and give that object to Jackson to serialize it into required JSON structure.
There are bunch of #Json annotations you can use to allow or not null or empty values, change property names, exclude Java class properties to be serialized and so, and so... All is up to you... good luck!
Consider the following json, getting from an public API:
anyObject : {
attributes: [
{
"name":"anyName",
"value":"anyValue"
},
{
"name":"anyName",
"value":
{
"key":"anyKey",
"label":"anyLabel"
}
}
]
}
As you can see, sometimes the value is a simple string and sometimes its an object. Is it somehow possible to deserialize those kind of json-results, to something like:
class AnyObject {
List<Attribute> attributes;
}
class Attribute {
private String key;
private String label;
}
How would I design my model to cover both cases. Is that possible ?
Despite being hard to manage as others have pointed out, you can do what you want. Add a custom deserializer to handle this situation. I rewrote your beans because I felt your Attribute class was a bit misleading. The AttributeEntry class in the object that is an entry in that "attributes" list. The ValueObject is the class that represents that "key"/"label" object. Those beans are below, but here's the custom deserializer. The idea is to check the type in the JSON, and instantiate the appropriate AttributeEntry based on its "value" type.
public class AttributeDeserializer extends JsonDeserializer<AttributeEntry> {
#Override
public AttributeEntry deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode root = p.readValueAsTree();
String name = root.get("name").asText();
if (root.get("value").isObject()) {
// use your object mapper here, this is just an example
ValueObject attribute = new ObjectMapper().readValue(root.get("value").asText(), ValueObject.class);
return new AttributeEntry(name, attribute);
} else if (root.get("value").isTextual()) {
String stringValue = root.get("value").asText();
return new AttributeEntry(name, stringValue);
} else {
return null; // or whatever
}
}
}
Because of this ambiguous type inconvenience, you will have to do some type checking throughout your code base.
You can then add this custom deserializer to your object mapper like so:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(AttributeEntry.class, new AttributeDeserializer());
objectMapper.registerModule(simpleModule);
Here's the AttributeEntry:
public class AttributeEntry {
private String name;
private Object value;
public AttributeEntry(String name, String value) {
this.name = name;
this.value = value;
}
public AttributeEntry(String name, ValueObject attributes) {
this.name = name;
this.value = attributes;
}
/* getters/setters */
}
Here's the ValueObject:
public class ValueObject {
private String key;
private String label;
/* getters/setters */
}
I am using Jackson for JSON serialization of a list of objects.
Here is what I get:
{"ArrayList":[{"id":1,"name":"test name"}]}
But I want this :
{"rootname":[{"id":1,"name":"test name"}]} // ie showing the string I want as the root name.
Below is my approach to this:
Interface:
public interface MyInterface {
public long getId();
public String getName();
}
Implementation class:
#JsonRootName(value = "rootname")
public class MyImpl implements MyInterface {
private final long id;
private String name;
public MyImpl(final long id,final name) {
this.id = id;
this.name = name;
}
// getters
}
JSon serialization:
public class MySerializer {
public static String serializeList(final List<MyInterface> lists) {
//check for null value.Throw Exception
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
return mapper.writeValueAsString(lists);
}
}
Test:
final List<MyInterface> list = new ArrayList<MyImpl>();
MyImpl item = new MyImpl(1L,"test name");
list.add(item);
final String json = MySerializer.serializeList(list);
System.out.println(json);
Here is what I get:
{"ArrayList":[{"id":1,"name":"test name"}]}
But I want this :
{"rootname":[{"id":1,"name":"test name"}]} // ie showing the string I want as the root name.
I have tried all suggested solutions I could find but failed to achieve my goal. I have looked at:
Jackson : custom collection serialization to JSON
How do I rename the root key of a JSON with Java Jackson?
Jackson : custom collection serialization to JSON
Or am I missing something? I am using jackson 1.9.12 for this. Any help in this regard is welcome.
Well, by default Jackson uses one of two annotations when trying to determine the root name to be displayed for wrapped values - #XmlRootElement or #JsonRootName. It expects this annotation to be on the type being serialized, else it will use the simple name of the type as the root name.
In your case, you are serializing a list, which is why the root name is 'ArrayList' (simple name of the type being serialized). Each element in the list may be of a type annotated with #JsonRootName, but the list itself is not.
When the root value you are trying to wrap is a collection then you need some way of defining the wrap name:
Holder/Wrapper Class
You can create a wrapper class to hold the list, with an annotation to define the desired property name (you only need to use this method when you do not have direct control of the ObjectMapper/JSON transformation process):
class MyInterfaceList {
#JsonProperty("rootname")
private List<MyInterface> list;
public List<MyInterface> getList() {
return list;
}
public void setList(List<MyInterface> list) {
this.list = list;
}
}
final List<MyInterface> lists = new ArrayList<MyInterface>(4);
lists.add(new MyImpl(1L, "test name"));
MyInterfaceList listHolder = new MyInterfaceList();
listHolder.setList(lists);
final String json = mapper.writeValueAsString(listHolder);
Object Writer
This is the preferable option. Use a configured ObjectWriter instance to generate the JSON. In particular, we are interested in the withRootName method:
final List<MyInterface> lists = new ArrayList<MyInterface>(4);
lists.add(new MyImpl(1L, "test name"));
final ObjectWriter writer = mapper.writer().withRootName("rootName");
final String json = writer.writeValueAsString(lists);
I know, I am late , but I have better approach which don't require Holder/Wrapper Class. It picks root key from annotation.
package com.test;
import com.fasterxml.jackson.annotation.JsonRootName;
#JsonRootName("Products")
public class ProductDTO {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Here is test class:-
package com.test;
import java.io.IOException;
import java.util.ArrayList;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ProductDTOTestCase {
#Test
public void testPersistAndFindById() throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
ProductDTO productDTO = new ProductDTO();
productDTO.setDescription("Product 4 - Test");
ArrayList<ProductDTO> arrayList = new ArrayList<ProductDTO>();
arrayList.add(productDTO);
String rootName = ProductDTO.class.getAnnotation(JsonRootName.class).value();
System.out.println(mapper.writer().withRootName(rootName).writeValueAsString(arrayList));
}
}
It will give following output
{"Products":[{"name":null,"description":"Product 4 - Test"}]}
#JsonTypeName("usuarios")
#JsonTypeInfo(include= JsonTypeInfo.As.WRAPPER_OBJECT,use= JsonTypeInfo.Id.NAME)
public class UsuarioDT extends ArrayList<Usuario> {
#JsonProperty("rowsAffected")
private Integer afectados;
public Integer getAfectados() {
return afectados;
}
public void setAfectados(Integer afectados) {
this.afectados = afectados;
}
}
You need to use this annotation at the top of the class
#JsonTypeName("rootname")