使用Jackson进行动态序列化-删除具有特定注释的字段 [英] Dynamic serialization using Jackson - removing fields with specific annotations

查看:576
本文介绍了使用Jackson进行动态序列化-删除具有特定注释的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

沿着创建注释的路径前进,该注释将动态确定字段是否应该序列化.

Went down a path of creating an annotation that would dynamic determine whether a field should be serialized or not.

注释的实现如下:

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = HiddenFieldSerializer.class)
@Target(value = ElementType.FIELD)
public @interface Hidden {
}

现在为序列化器提供代码:

Now the code for the Serializer:

public class HiddenFieldSerializer
        extends StdSerializer<String>
        implements ContextualSerializer {

    public HiddenFieldSerializer() {
        super(String.class);
    }

    @Override
    public void serialize(String value,
                          JsonGenerator jgen,
                          SerializerProvider provider) {
        try {
            provider.defaultSerializeNull(jgen);
        } catch (IOException e) {
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov,
                                              BeanProperty property) {
        return shouldHide() ?
                new HiddenFieldSerializer() : new StringSerializer();
    }

    public boolean shouldHide() {
        /* Simplifying this */
        return Boolean.TRUE;
    }
}

一些代码来说明其工作原理:

A little bit of code to show how it works:

public class Test {
    static final ObjectMapper mapper = new ObjectMapper()
            .setSerializationInclusion(Include.NON_NULL)
            .setSerializationInclusion(Include.NON_EMPTY);

    static class User {
        @JsonProperty
        String username;

        @Hidden
        @JsonProperty
        String pin;
    }

    public static void main(String... args)
            throws JsonProcessingException {

        final POC.User u = new POC.User();
        u.username = "harry_potter";
        u.pin = "1298";

        System.out.println(mapper.writeValueAsString(u));
    }
}

输出如下:

{"username":"harry_potter","pin":null}

如何将现场引脚从序列化中删除而不是将其为null?显然,在这种情况下,设置映射器的属性的用户很少.有什么建议?有什么想法吗?也许整个事情都不是个好主意?

How do I get the field pin to be removed from the serialization instead of it being null? Obviously setting the mapper's properties was of very little user in such a context. Any suggestions? Thoughts? Maybe the whole thing is a bad idea?

理想情况下,我应该能够看到以下内容:

Ideally I should be able to see the following:

{"username":"harry_potter"}

推荐答案

尚不清楚是要静态地忽略给定的属性还是动态地忽略给定的属性.无论如何,看来您已经对其进行了过度设计.

It's not clear whether you want to ignore a given property statically or dynamically. Anyways, looks like you have over-engineered it.

首先,我想确保您遇到

First of all, I want to make sure that you came across @JsonIgnore before. If it doesn't suit your needs, you could define your custom ignore annotation as following:

@Retention(RetentionPolicy.RUNTIME)
public @interface Hidden {

}

然后选择最适合您需求的方法:

Then pick the approach that best suit your needs:

扩展 并覆盖检查忽略标记的方法:

Extend JacksonAnnotationIntrospector and override the method that checks for the ignore marker:

public class CustomAnnotationIntrospector extends JacksonAnnotationIntrospector {

    @Override
    public boolean hasIgnoreMarker(AnnotatedMember m) {
        return super.hasIgnoreMarker(m) || m.hasAnnotation(Hidden.class);
    }
}

配置 ObjectMapper 使用注释内省者:

Configure ObjectMapper to use your annotation introspector:

ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new CustomAnnotationIntrospector());

注释内省每个类仅出现一次,因此您不能动态更改使用的条件(如果有).可以在此答案中看到类似的示例.

The annotation introspection occurs only once per class so you can not dynamically change the criteria you use (if any). A similar example can be seen in this answer.

扩展 修改将要序列化的属性:

Extend BeanSerializerModifier to modify the properties that will be serialized:

public class CustomBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, 
            BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        return beanProperties.stream()
                .filter(property -> property.getAnnotation(Hidden.class) == null)
                .collect(Collectors.toList());
    }
}

然后将其添加到 Module 并将其注册到您的

Then add it to a Module and register it to your ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new CustomBeanSerializerModifier());
    }
});

这种方法允许您动态忽略属性.

This approach allows you to ignore properties dynamically.

这篇关于使用Jackson进行动态序列化-删除具有特定注释的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆