如何在序列化过程中跳过某些类型的字段?

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

我有一个 Spring AOP 服务,它拦截许多不同的第三方控制器端点。我的服务运行一个端点,获取结果 DTO,使用 ObjectMapper 将 DTO 序列化为 json,将 json 发送到 Kafka 并将 DTO 返回到外部。问题是:服务不应序列化特定类型的字段(例如 MultipartFile)。我无法使用 @JsonIgnore 注释,因为 DTO 应该不加更改地返回到外部。 我可以让 ObjectMapper 跳过某些类型的字段吗?或者,也许复制 DTO 并通过反射将此字段设置为 null?

java json serialization reflection jackson
1个回答
0
投票

永远记住 Jackson 是真正的魔法,并且可以无限定制:)

有很多方法可以实现你想要的。 Mixin 是一个简单的方法。

混音

假设您有以下 DTO 类并希望排除

File

public class SimpleDTO {

    private final File file;
    private final String name;

    @JsonCreator
    public SimpleDTO(@JsonProperty("file") File file, @JsonProperty("name") String name) {
        this.file = file;
        this.name = name;
    }

    public File getFile() {
        return file;
    }

    public String getName() {
        return name;
    }
}

您可以创建混合,例如:

@JsonIgnoreType
public interface FileMixin {}

然后序列化时使用:

//Pretend the File class was annotated by @JsonIgnoreType
ObjectMapper mapper = new ObjectMapper().addMixIn(File.class, FileMixin.class);

String serialized = mapper.writeValueAsString(new SimpleDTO(new File("/tmp/simple.txt"), "A kewl name"));
System.out.println(serialized); //Prints {"name":"A kewl name"}

除了

@JsonIgnoreType
,您还可以将
@JsonIgnore
混合到
file
SimpleDTO
或任何其他 Jackson 注释中的
@JsonIgnoreProperties(value = { "file" })
字段。以下是用于忽略字段的注释概述

注意:不要每次都创建新的

ObjectMapper
。配置一个实例进行序列化并永久共享。

编程配置

Mix-ins 允许您从外部添加注释,但注释仍然是静态配置。如果您必须动态选择要忽略的内容,则注释(无论是否混合)都不够。 Jackson 很神奇,他可以让你以编程方式实现任何可以通过注释完成的事情:

public class FieldFilteringIntrospector extends NopAnnotationIntrospector {

    private final Set<Class<?>> ignoredTypes;

    public FieldFilteringIntrospector(Set<Class<?>> ignoredTypes) {
        this.ignoredTypes = Collections.unmodifiableSet(ignoredTypes);
    }

    public FieldFilteringIntrospector(Class<?>... ignoredTypes) {
        this.ignoredTypes = Arrays.stream(ignoredTypes).collect(Collectors.toUnmodifiableSet());
    }

    @Override
    public Boolean isIgnorableType(AnnotatedClass ac) {
        return ignoredTypes.contains(ac.getRawType());
    }
}

然后序列化时使用:

SimpleModule module = new SimpleModule("type-filter-module") {
    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.insertAnnotationIntrospector(new FieldFilteringIntrospector(File.class));
    }
};
ObjectMapper mapper = new ObjectMapper().registerModule(module);

String serialized = mapper.writeValueAsString(new SimpleDTO(new File("/tmp/simple.txt"), "A kewl name"));
System.out.println(serialized); //Prints {"name":"A kewl name"}

通过重写

NopAnnotationIntrospector
中的其他方法,您可以模拟其他注释、
@JsonIgnore
等。

注意:再次强调,仅创建一次

ObjectMapper

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