I have a json response coming from MongoDB and in its current form I have a pojo like below to bind these month field values:-
#JsonProperty("Feb-2017")
private Float feb2017;
The problem is that these month names change with time and those values will no longer be bound to the java object.The POJO in turn is an attribute of two other objects that represent this json. I cannot change the json structure in the Db and have tried creating this pojo at runtime following this answer but I cannot figure out how to reference this object across other POJOs .
Is there any other way I could approach this problem?
Thanks.
In your POJO, add a class member as follows:
private Map<String, Object> months = new HashMap<>();
Then create a method annotated with #JsonAnySetter:
#JsonAnySetter
public void set(String key, Object value) {
months.put(key, value);
}
This method works as a fallback handler for all unrecognized properties found in the JSON document.
Related
I am new with spring and I want the json response of my class
public class Mapping { public String name; public Object value; }
be changed from
{"name" : 'value of field name', "value": 'value of field value'}
to
{'value of field name' : 'value of field value'}
I tried #JsonValue and #JsonKey but they didn`t work. how can I do this.
edit:
I want to set the value of key dynamically and based on value of the field name.
edit_P2:
this class, is a model for a single field in json, means an object of it must hold one key and value of my json, like a map, it has key and values, and what i want is to store key in field 'name' and the value in outher field, so when i return this object, it returns the string in field 'name' as key and the other one as value, lets assume name="the key" and value="the value", i want it to be return as "the key":"the value".
Edited in reaction to your comment:
Have your class changed from
public class Mapping {
public String name;
public Object value;
}
to simply this:
public class Mapping {
public String name;
}
and in your code to this:
Mapping myMapping = new Mapping();
myMapping.name = "myValue";
This will be parsed to JSON: {"name":"myValue"}
Additional edit
OK, I think I understood what you want and I think it might be impossible in a single json serialization. Your options would be to create a custom serializer See this article: Jackson – Custom Serializer. Or (in my opinion simpler way) add a method to your class toMap() that will produce your desired map and than convert that map to Json. That will give you desired Json. BTW for simple Json serializer/deserializer that is a wrapper over Json-Jackson library look here: JsonUtils. The library could be found as Maven artifact and on Github (including source code and Javadoc).
Original answer:
You need to use annotation #JsonProperty and its attribute "name". Here is a good article about it: Jackson – Change Name of Field
I've a model with field annotated as a:
#JsonTypeInfo(use = CLASS)
private Object dudClass;
The main problem is when I try to deserialize this object and I don't have this dudClass instance on classpath I will receive an exception:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid type id 'pl.erbel.DudClass' (for id type 'Id.class'): no such class found.
Is it any easy way to just ignore this exception? I don't want to ignore serialization/deserialization cause I need this in different module. I just have a two clients: one with DudClass on classpath and the seconde one without that class.
It might not be the perfect solution but this is a work around. Instead of having dudClass in your POJO you can make use of the additional properties using JsonAnyGetter and JsonAnySetter. You need to remove the dudClass from your parent class and include the following code
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
What this does is while deserializing instead of trying to set the dudClass everytime it sets any additional objects that comes along in the response to the Map with object name as the key (in your case it's dudClass) and the object contents as the value. You just have see if the Map has dudClass key present or not.
Let me know if this doesn't answer your issue or need clarification!
I am building a REST API with a payload that has a property called jsonContent, which holds any valid json.
{
"name":"foo",
"jsonContent":{ "abc":"My content"}
}
On the server side I want to map the it to a generic java object ,and eventually save the whole object to mongodb
private String name;
private ?????? jsonContent
I am using jackson for mapping json to java. How do I declare my java object so any json content can be used.
Use JsonNode:
private JsonNode jsonContent;
I answer my own question, Following worked just fine for me
private Map<String,Object> jsonContent;
I have a Map<String, Object> which I am using as a mapping for a JSON document, however want to create and maintain Java type information at the same time as retaining the structure of the document.
I'm attempting to use Jackson to create the document and it seems to work fine but I'm seeing something strange when attempting to deserialize it. A very simple serialization example:
final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.EXTERNAL_PROPERTY);
final Map<String, Object> map = Maps.newHashMap();
map.put("test", new Date());
final String ser = mapper.writeValueAsString(map);
final Map<String, Object> deser = mapper.readValue(ser, new TypeReference<HashMap<String, Object>>(){});
System.err.println(deser.get("test").getClass());
Gives the serialized form {"test":1410721662084,"#class":"java.util.Date"} which seems fine but when deserializing returns the type of "test" to be Long.
If I change the type serialization to use WRAPPER_ARRAY rather than EXTERNAL_PROPERTY then the type of "test" is correctly returned as Date, but doing this alters the structure of the JSON document so is not something I'm allowed to do. How do I retain the structure of the document as well as allow deserialization back to the correct types?
This is against Jackson 2.4.2.
Deserialization with maps is always tricky as maps don't preserve type information, which makes Jackson resort to #class and that not something you usually want. Instead, you can create a simple class:
public class TestClass {
private Date test;
//getters and setters omitted
}
This class has concrete structure and JSON will serialize it as
{ "test" : 1410721662084}
which is much cleaner and type-safe representation of your object. Then you just need to pass TestClass.class to readValue() method and your test attribute will be magically converted to proper type (Date)
Is there a way to modify the field of POJO with new property(like using MixIns or #JSONProperty) and get the modified POJO back ? (A way to add/modify field of a POJO dynamically ?)
Like I have a class
class PojoA<T>{
private T data;//field to be modified as NewData
}
So, I tried with MixIns like
public interface PojoMixIn<T> {
#JsonProperty("NewData")
T getData();
}
Now to get the modified field, I use ObjectMapper
mapper.addMixInAnnotations(PojoA.class,PojoMixIn.class);
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(pojoA);
The actual result is a String, but can I be able to get the modified POJO?