How to use mixin to ignore a field when using ObjectMapper? - java

class Apple{
#JsonProperty("colour")
public String colour;
#JsonProperty("dummy_params")
public DummyParams dummyParams;
}
public abstract class AppleMixin{
#JsonIgnore
#JsonProperty("dummy_params")
public DummyParams dummyParams;
}
I am trying to ignore dummyParams field when using ObjectMapper
class Tester{
public static void main(){
Apple app = new Apple();
app.setColor("red");
app.setDummyParams(new DummyParams("1","2"));
ObjectMapper objecMapper = new ObjectMapper();
objecMapper.addMixIn(Apple.class, AppleMixin.class);
String result = objecMapper.writeValueAsString(exec);
}
}
I am using com.fasterxml.jackson.databind.ObjectMapper
Expected Result : {"colour": "red"}
Actual Result : {"colour":"red", "dummyParams":{"dummyOne" :1,"dummyTwo":2}}
The mixin is not working.Am I doing wrong?

Related

How to write custom serializer for proxy classes

I need to serialize/deserialize a POJO with enum. I have the following DTO:
public enum MyEnum {
VAL1("val1"),
VAL2("val2") {
#Override
public String getValue() {
return "test2";
}
};
private final String name;
MyEnum(String name) {
this.name = name;
}
public String getValue() {
return name;
}
}
public class MyPojo {
public MyEnum prop;
}
public static void main(String... args) {
Gson gson = new GsonBuilder().registerTypeAdapter(MyEnum.class, new MyEnumSeserializer());
MyPojo p = new MyPojo();
p.prop = MyEnum.VAL2; // and I get MyEnum$1.class and My serializer doesn't work
String json = gson.toJson(p);
MyPojo p1 = gson.fromJson(json, MyPojo.class);
}
How can I write a custom serializer/deserializer for proxy classes using Gson library? I can't use another library.
I've been found the solution. Need to change
new GsonBuilder().registerTypeAdapter(MyEnum.class, new MyEnumSeserializer());
to
new GsonBuilder(). registerTypeHierarchyAdapter(MyEnum.class, new MyEnumSeserializer());
and all work fine.

Ignore properties marked with specific annotation

I have ObjectMapper instance:
ObjectMapper mapper = new ObjectMapper();
In runtime want to serialize instance of class. What is the class the program doesn't known. It's object instance of parameterized type T.
How to ignore all properties (fields and getters) which marked specified annotation (javax.persistence.Id) ?
Example:
public static class PojoTest {
#Id
public String idTest;
public String id;
}
public void serialize(Object object) {
ObjectMapper objectMapper = new ObjectMapper();
// TODO ignore property mark #Id annotation
Map<Object, Object> map = objectMapper.convertValue(object, Map.class);
assertFalse(map.containsKey("idTest"));
}
public void test() {
PojoTest pojoTest = new PojoTest();
pojoTest.id = "foo";
pojoTest.idTest = "bar";
serialize(pojoTest);
}
You can implement a new com.fasterxml.jackson.databind.AnnotationIntrospector class where you can extend hasIgnoreMarker method:
static class IdIgnoreAnnotationIntrospector extends AnnotationIntrospector {
#Override
public Version version() {
return new Version(1,0,0,"Ignore #Id", "group.id", "artifact.id");
}
#Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
return hasIdAnnotation(m);
}
boolean hasIdAnnotation(AnnotatedMember member) {
return member.getAnnotation(Id.class) != null;
}
}
Now you need to register this introspector:
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(new JacksonAnnotationIntrospector(), new IdIgnoreAnnotationIntrospector()));
Now you can ignore all fields marked with #Id annotation.

Jackson not serializing property

I have the following two enums
public enum Action {
ACTION1,
ACTION2,
ACTION3;
}
public enum EntityType {
ENTITYTYPE1,
ENTITYTYPE2;
}
and the following class
public class EntityIdentityDto implements MetaData {
private String id;
private EntityType entityType;
private Action action;
private Map<String, Object> properties = new HashMap();
public String getId() {
return this.id;
}
public EntityType getEntityType() {
return this.entityType;
}
public Action getAction() {
return this.action;
}
public Map<String, Object> getProperties() {
return this.properties;
}
public void setId(String id) {
this.id = id;
}
public void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
public void setAction(Action action) {
this.action = action;
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
public EntityIdentityDto() {
}
}
When using Jackson 2.9.8 to serialize into Json as per below
public class TestMe {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
EntityIdentityDto entityIdentityDto = new EntityIdentityDto();
entityIdentityDto.setEntityType(EntityType.ENTITYTYPE1);
entityIdentityDto.setAction(Action.ACTION1);
entityIdentityDto.setId("OOO");
String out = objectMapper.writeValueAsString(entityIdentityDto);
System.out.println(out);
}
}
The output is
{"id":"OOO","action":"ACTION1","properties":{}}
I am expecting to so the entityType field serialized as well but this is missing. This is what I expect to see
{"id":"OOO","entityType": "ENTITYTYPE1", "action":"ACTION1","properties":{}}
If instead of Jackson I use Gson as per below
public class TestMe {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
EntityIdentityDto entityIdentityDto = new EntityIdentityDto();
entityIdentityDto.setEntityType(EntityType.SYSTEM);
entityIdentityDto.setAction(Action.SYNC);
entityIdentityDto.setId("OOO");
System.out.println(new Gson().toJson(entityIdentityDto));
}
}
The output is as expected
{"id":"OOO","entityType":"ENTITYTYPE1","action":"ACTION1","properties":{}}
Why is the entityType field missing in the Json generated using Jackson ?
It is interesting that action gets serialized but entityType does not even though they are structurally identical and used identically in the EntityIdentityDto
Probably you do not have getter for entityType property. Add getter or use setVisibility method:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
See also:
how to specify jackson to only use fields - preferably globally
Jackson – Decide What Fields Get Serialized/Deserialized
Exclude Fields from Serialization in Gson
The issue was with my EntityIdentityDto class which implements the following interface
public interface MetaData {
String getId();
Map<String, Object> getProperties();
void setProperties(Map<String, Object> properties);
#JsonIgnore
EntityType getEntityType();
}
The JsonIgnore at the interface level is the reason why it was not being serialized. After dropping the JsonIgnore all works as expected now.

Instruct Jackson to serialize from given method

I'm using Jackson library vs 2.6.3. I would like to define the serialization method inside a class and I would like to instruct Jackson to call this method when an object is serialized.
E.g.
public interface AClass {
default String toJSON(){
return "{JSON}";
}
}
and then I have
public class AnotherClass {
AClass aClass;
}
When I serialize AnotherClass, I "pretend" that method toJson from AClass is called to return the JSON view of the object.
Is there any annotation that I can use on AClass?
Yes, this is possible using #JsonValue and #JsonRawValue annotations. Here is an example:
public class JacksonValue {
public interface AClass {
#JsonValue
#JsonRawValue
default String toJSON(){
return "{\"JSON\":true}";
}
}
public static class AnotherClass {
#JsonProperty
AClass aClass = new AClass() {};
}
public static void main(String[] args) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new AnotherClass()));
}
}
Output:
{"aClass":{"JSON":true}}

how to only serialize properties annotated with a custom annotation

We use jackson throughout our application to serialize and deserialize Java objects to JSON. It works great.
Is it possible, perhaps through a custom serializer, to serialize only properties of a Java object that are Annotated with a custom annotation?
So, given the custom annotation:
public #interface SpecialField {}
And the following bean
public SomeBean {
#SpecialField
private Object propertyIncluded;
private Object propertyExcluded;
}
What would a custom serializer (or some equivalent mechanism) look like to serialize propertyIncluded (using the normal jackson object mapper) and ignore propertyExcluded?
We can't use standard jackson annotations (#JsonIgnore) in this use case because it would break our other serialization uses cases in the application.
While this might not be quite what your looking for, It is possible to make the jackson engine serialize objects differently via some tweaking. In my example below I create two types of serializers which will or wont serialize a field marked as transient.
import java.io.Serializable;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.map.ObjectMapper;
public class Test {
public static void main(String[] args) throws Exception {
ISerializer d = new Doesnt();
ISerializer o = new Observes();
SomeObject obj = new SomeObject();
System.out.println("Doesnt: " + d.serialize(obj));
System.out.println("Observes: " + o.serialize(obj));
}
public static class Doesnt implements ISerializer<SomeObject> {
#Override
public String serialize(SomeObject o) throws Exception {
ObjectMapper om = new ObjectMapper();
om.setVisibilityChecker(
om.getSerializationConfig().
getDefaultVisibilityChecker().
withFieldVisibility(JsonAutoDetect.Visibility.ANY).
withGetterVisibility(JsonAutoDetect.Visibility.ANY));
return om.writeValueAsString(o);
}
}
public static class Observes implements ISerializer<SomeObject> {
#Override
public String serialize(SomeObject o) throws Exception {
ObjectMapper om = new ObjectMapper();
om.setVisibilityChecker(
om.getSerializationConfig().
getDefaultVisibilityChecker().
withFieldVisibility(JsonAutoDetect.Visibility.ANY).
withGetterVisibility(JsonAutoDetect.Visibility.NONE));
return om.writeValueAsString(o);
}
}
public interface ISerializer<T> {
public String serialize(T o) throws Exception;
}
public static class SomeObject implements Serializable {
private static final long serialVersionUID = 745063791749142843L;
private transient String myVar = "Transient";
private String myOther = "Not Transient";
public String getMyVar() {
return myVar;
}
public void setMyVar(String myVar) {
this.myVar = myVar;
}
public String getMyOther() {
return myOther;
}
public void setMyOther(String myOther) {
this.myOther = myOther;
}
}
}
output:
Doesnt: {"myVar":"Transient","myOther":"Not Transient"}
Observes: {"myOther":"Not Transient"}
I would think it would be fairly easy to change serializers to extend the JsonSerializer class, and do something similar in them.

Categories

Resources