I have an entity with multiple @ManyToOne
associations. I am using spring-boot to expose a REST API. Currently, I have multiple REST API's which return a JSON response of the whole entity, including associations.
But I don't want to serialize all associated objects in all REST APIs.
For example
So, in my serialization process, I want to ignore all association except associationA for API-1.
For API-2 I want to ignore other associations except A and B
How do I dynamically ignore these properties during Jackson serialization?
Notes: I'm using the same class for each; I am not interested in creating a DTO for each API.
Any suggestions are kingly appreciated.
WhenWritingDefault - The property is ignored on serialization if it's a reference type null , a nullable value type null , or a value type default . WhenWritingNull - The property is ignored on serialization if it's a reference type null , or a nullable value type null .
Overview So when Jackson is reading from JSON string, it will read the property and put into the target object. But when Jackson attempts to serialize the object, it will ignore the property. For this purpose, we'll use @JsonIgnore and @JsonIgnoreProperties.
The Jackson @JsonIgnore annotation can be used to ignore a certain property or field of a Java object. The property can be ignored both when reading JSON into Java objects and when writing Java objects into JSON.
I've put together three approaches for performing dynamic filtering in Jackson. One of them must suit your needs.
@JsonView
You could use @JsonView
:
public class Views {
interface Simple { }
interface Detailed extends Simple { }
}
public class Foo {
@JsonView(Views.Simple.class)
private String name;
@JsonView(Views.Detailed.class)
private String details;
// Getters and setters
}
@RequestMapping("/foo")
@JsonView(Views.Detailed.class)
public Foo getFoo() {
Foo foo = new Foo();
return foo;
}
Alternatively you can set the view dynamically with MappingJacksonValue
.
@RequestMapping("/foo")
public MappingJacksonValue getFoo() {
Foo foo = new Foo();
MappingJacksonValue result = new MappingJacksonValue(foo);
result.setSerializationView(Views.Detailed.class);
return result;
}
BeanSerializerModifier
You could extend BeanSerializerModifier
and then override the changeProperties()
method. It allows you to add, remove or replace any of properties for serialization, according to your needs:
public class CustomSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
// In this method you can add, remove or replace any of passed properties
return beanProperties;
}
}
Then register the serializer as a module in your ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new CustomSerializerModifier());
}
});
Check examples here and here.
@JsonFilter
with a SimpleBeanPropertyFilter
Another approach involves @JsonFilter
:
@JsonFilter("customPropertyFilter")
public class Foo {
private String name;
private String details;
// Getters and setters
}
Extend SimpleBeanPropertyFilter
and override the serializeAsField()
method according to your needs:
public class CustomPropertyFilter extends SimpleBeanPropertyFilter {
@Override
public void serializeAsField(Object pojo, JsonGenerator jgen,
SerializerProvider provider,
PropertyWriter writer) throws Exception {
// Serialize a field
// writer.serializeAsField(pojo, jgen, provider, writer);
// Omit a field from serialization
// writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
Then register the filter in your ObjectMapper
:
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("customPropertyFilter", new CustomPropertyFilter());
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
If you want to make your filter "global", that is, to be applied to all beans, you can create a mix-in class and annotate it with @JsonFilter("customPropertyFilter")
:
@JsonFilter("customPropertyFilter")
public class CustomPropertyFilterMixIn {
}
Then bind the mix-in class to Object
:
mapper.addMixIn(Object.class, CustomPropertyFilterMixIn.class);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With