JsonViewsを使用して、カスタムシリアライザーとカスタムプロパティフィルターを組み合わせて使用できます。これがJackson2.0で動作するコードです
カスタム注釈を定義します。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FilterUsingView {
Class<?>[] value();
}
いくつかのビューを定義します。
// Define your views here
public static class Views {
public class Public {};
public class Internal extends Public{};
}
次に、このようにエンティティを記述できます。を使用する代わりに、独自の注釈を定義できることに注意してください@JsonView
。
public class Foo {
@JsonView(Views.Public.class)
public String bar;
@JsonView(Views.Internal.class)
public String biz;
}
public class FooContainer {
public Foo fooA;
@FilterUsingView(Views.Public.class)
public Foo fooB;
}
次に、ここからコードが始まります:)最初にカスタムフィルター:
public static class CustomFilter extends SimpleBeanPropertyFilter {
private Class<?>[] _nextViews;
public void setNextViews(Class<?>[] clazz){
_nextViews = clazz;
}
@Override
public void serializeAsField(Object bean, JsonGenerator jgen,
SerializerProvider prov, BeanPropertyWriter writer)
throws Exception {
Class<?>[] propViews = writer.getViews();
if(propViews != null && _nextViews != null){
for(Class<?> propView : propViews){
System.out.println(propView.getName());
for(Class<?> currentView : _nextViews){
if(!propView.isAssignableFrom(currentView)){
// Do the filtering!
return;
}
}
}
}
// The property is not filtered
writer.serializeAsField(bean, jgen, prov);
}
}
AnnotationIntrospector
次に、 2つのことを行うカスタム:
- 任意のBeanに対してカスタムフィルターを有効にします...クラスで別のフィルターが定義されていない限り(つまり、私が言っていることを理解している場合は、両方を使用することはできません)
@FilterUsingView
彼が注釈を見つけた場合は、CustomSerializerを有効にします。
これがコードです
public class CustomAnnotationIntrospector extends AnnotationIntrospector {
@Override
public Version version() {
return DatabindVersion.instance.version();
}
@Override
public Object findFilterId(AnnotatedClass ac) {
// CustomFilter is used for EVERY Bean, unless another filter is defined
Object id = super.findFilterId(ac);
if (id == null) {
id = "CustomFilter";
}
return id;
}
@Override
public Object findSerializer(Annotated am) {
FilterUsingView annotation = am.getAnnotation(FilterUsingView.class);
if(annotation == null){
return null;
}
return new CustomSerializer(annotation.value());
}
}
これがカスタムシリアライザーです。アノテーションの値をカスタムフィルターに渡すだけで、デフォルトのシリアライザーに処理を任せることができます。
public class CustomSerializer extends JsonSerializer<Object> {
private Class<?>[] _activeViews;
public CustomSerializer(Class<?>[] view){
_activeViews = view;
}
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
BeanPropertyFilter filter = provider.getConfig().getFilterProvider().findFilter("CustomFilter");
if(filter instanceof CustomFilter){
CustomFilter customFilter = (CustomFilter) filter;
// Tell the filter that we will filter our next property
customFilter.setNextViews(_activeViews);
provider.defaultSerializeValue(value, jgen);
// Property has been filtered and written, do not filter anymore
customFilter.setNextViews(null);
}else{
// You did not define a CustomFilter ? Well this serializer is useless...
provider.defaultSerializeValue(value, jgen);
}
}
}
ついに !これをすべてまとめましょう:
public class CustomModule extends SimpleModule {
public CustomModule() {
super("custom-module", new Version(0, 1, 0, "", "", ""));
}
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
AnnotationIntrospector ai = new CustomAnnotationIntrospector();
context.appendAnnotationIntrospector(ai);
}
}
@Test
public void customField() throws Exception {
FooContainer object = new FooContainer();
object.fooA = new Foo();
object.fooA.bar = "asdf";
object.fooA.biz = "fdsa";
object.fooB = new Foo();
object.fooB.bar = "qwer";
object.fooB.biz = "test";
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new CustomModule());
FilterProvider fp = new SimpleFilterProvider().addFilter("CustomFilter", new CustomFilter());
StringWriter writer = new StringWriter();
mapper.writer(fp).writeValue(writer, object);
String expected = "{\"fooA\":{\"bar\":\"asdf\",\"biz\":\"fdsa\"},\"fooB\":{\"bar\":\"qwer\"}}";
Assert.assertEquals(expected, writer.toString());
}