使用 Jackson 进行动态序列化 - 删除具有特定注释的字段

问题描述 投票:0回答:2

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

注解的实现如下:

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

现在是序列化器的代码:

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;
    }
}

一些代码来展示它是如何工作的:

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}

如何从序列化中删除字段引脚而不是将其设置为空?显然,在这种情况下,设置映射器的属性很少有用户关注。有什么建议么?想法?也许整件事都是个坏主意?

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

{"username":"harry_potter"}
java serialization jackson annotations
2个回答
2
投票

尚不清楚您是否想要静态动态忽略给定属性。不管怎样,看起来你已经过度设计了。

首先,我想确保您之前遇到过

@JsonIgnore
。如果它不满足您的需求,您可以定义自定义忽略注释,如下所示:

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

}

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

方法#1

扩展

JacksonAnnotationIntrospector
并重写检查忽略标记的方法:

public class CustomAnnotationIntrospector extends JacksonAnnotationIntrospector {

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

配置

ObjectMapper
以使用注释内省器:

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

注释自省每个类仅发生一次,因此您无法动态更改您使用的标准(如果有)。类似的例子可以在这个answer中看到。

方法#2

扩展

BeanSerializerModifier
来修改将要序列化的属性:

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
并将其注册到您的
ObjectMapper
:

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

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

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


0
投票

我也遇到了同样的问题,我必须在序列化期间检查某些权限,但它第一次就被缓存了。

© www.soinside.com 2019 - 2024. All rights reserved.