如何有条件地序列化字段

发布于 2025-01-09 15:17:05 字数 2046 浏览 0 评论 0原文

我想有条件地序列化一个字段。我想出了如何有条件地忽略一个字段,

public class NologIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public boolean hasIgnoreMarker(AnnotatedMember m) {
        boolean noLogOnClass = m.getDeclaringClass().getAnnotation(NoLog.class) != null;
        return m.hasAnnotation(NoLog.class) || super.hasIgnoreMarker(m) || noLogOnClass;
    }
}

但我真正想做的是编辑该字段。所以如果我有的话,

@Getter
@Setter
@NoArgsConstructor
public class MyObject1 {
    public String field1 = "field1";
    @NoLog
    public String field2 = "field2";

    public static void main(String[] args) throws JsonProcessingException {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setAnnotationIntrospector(new NologIntrospector());
        final MyObject1 myObject1 = new MyObject1();
        System.out.println(objectMapper.writeValueAsString(myObject1));
    }
}

我会得到

{"field1":"field1"}

Field2 被正确忽略。但我真正想要的是

{"field1":"field1", "field2": "<***redacted***>"}

我有另一个注释,@MaskSensitiveData

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = MaskSensitiveDataSerializer.class)
public @interface MaskSensitiveData {
}

public class MaskSensitiveDataSerializer extends StdSerializer<Object> {

    protected MaskSensitiveDataSerializer() {
        this(null);
    }

    public MaskSensitiveDataSerializer(Class<Object> t) {
        super(t);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (!(value instanceof  String)) {
            throw new RuntimeException("MaskSensitiveData annotation is only valid for string");
        }
        gen.writeString("<*** redacted ***>");
    }
}

所以我想做的就是将它们结合起来。因此,如果某个字段具有特殊注释并且我正在使用我的内省器,那么只有那时我才想要编辑该字段。否则,该字段应该正常序列化。

I want to conditionally serialize a field. I figured out how to conditionally ignore a field with

public class NologIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public boolean hasIgnoreMarker(AnnotatedMember m) {
        boolean noLogOnClass = m.getDeclaringClass().getAnnotation(NoLog.class) != null;
        return m.hasAnnotation(NoLog.class) || super.hasIgnoreMarker(m) || noLogOnClass;
    }
}

But what I really want to do is to redact the field. So if I have

@Getter
@Setter
@NoArgsConstructor
public class MyObject1 {
    public String field1 = "field1";
    @NoLog
    public String field2 = "field2";

    public static void main(String[] args) throws JsonProcessingException {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setAnnotationIntrospector(new NologIntrospector());
        final MyObject1 myObject1 = new MyObject1();
        System.out.println(objectMapper.writeValueAsString(myObject1));
    }
}

I get

{"field1":"field1"}

Field2 is correctly ignored. But what I really want is

{"field1":"field1", "field2": "<***redacted***>"}

I have another annotation, @MaskSensitiveData

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = MaskSensitiveDataSerializer.class)
public @interface MaskSensitiveData {
}

public class MaskSensitiveDataSerializer extends StdSerializer<Object> {

    protected MaskSensitiveDataSerializer() {
        this(null);
    }

    public MaskSensitiveDataSerializer(Class<Object> t) {
        super(t);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (!(value instanceof  String)) {
            throw new RuntimeException("MaskSensitiveData annotation is only valid for string");
        }
        gen.writeString("<*** redacted ***>");
    }
}

So what I want to do is combine them. So if a field has the special annotation and I am using my introspector, only then, do I want to redact the field. Otherwise, the field should be serialized normally.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

魔法少女 2025-01-16 15:17:05

而不是重写 NologIntrospector 中的 hasIgnoreMarker 方法。您需要重写findSerializer
这样,当启用内省器时,将使用自定义序列化器,否则它将使用原始序列化器。

public class NologIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public Object findSerializer(Annotated ann){
        if (ann.hasAnnotation(NoLog.class)) {
            return MaskSensitiveDataSerializer.class;
        }
        return super.findSerializer(ann);
    }
}

Instead of overriding method hasIgnoreMarker in NologIntrospector. You need to override findSerializer.
This way when your introspector is enabled the custom serializer will be used else it will use the original serializer.

public class NologIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public Object findSerializer(Annotated ann){
        if (ann.hasAnnotation(NoLog.class)) {
            return MaskSensitiveDataSerializer.class;
        }
        return super.findSerializer(ann);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文