编写半自定义反序列化器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写半自定义反序列化器相关的知识,希望对你有一定的参考价值。

我想编写一个仍然使用一些默认功能的自定义反序列化组件:

想象一下这些课程:

class Category {
    private Long id;
    private String name;
}

class Article {
    private Long id;
    private String title;
    private Category category;
}

这个JSON有效载荷:

{
  "id": 1,
  "title": "Pray for Notre Dame",
  "category_id": 5
}

根据我对在线阅读的各种文章的理解,我应该编写一个自定义反序列化器来处理我的category_id字段:

@JsonComponent
public class ArticleJsonDeserializer extends JsonDeserializer<Article> {

    @Override
    public Article deserialize(JsonParser jsonParser, 
      DeserializationContext deserializationContext) throws IOException, 
      JsonProcessingException {

        TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
        TextNode category = this.entityManager.getReference(Category.class, treeNode.get("category_id"));

        // The following lines bother me
        String title = treeNode.get("title");
        Long id = treeNode.get("id");

        return new Article(id, title, category);
    }
}

但是,实际上,我很乐意使用titleid字段的默认解串器功能,而无需重写此逻辑。

我怎样才能做到这一点?

答案

简短的回答

假设您在Article类中有一个默认构造函数,则以下内容应该有效:

Article article = jsonParser.getCodec().treeToValue(treeNode, Article.class);

然后在category中设置article

更长的答案

嗯......我认为你正在偷工减料,超越了定制反序列化器的用途。你可能不想创建这样的耦合。

或者,你可以使用@JsonIdentityInfoObjectIdResolver。你可以从这个answer中描述的方法中获得一些想法。

您可以使用考虑DTO,而不是在您的Web API中公开您的JPA实体。请参阅我之前在answer中描述的原因以供参考。然后你可以有一个映射层将你的实体映射到你的DTO,反之亦然。例如,如果您正在使用MapStruct,那么文档shows an example将介绍如何通过其ID解析实体。

以上是关于编写半自定义反序列化器的主要内容,如果未能解决你的问题,请参考以下文章

如何为计时时间戳使用自定义 serde 反序列化器?

在其他反序列化器中调用自定义 Jackson 反序列化器

是否可以在春季默认使用自定义序列化器/反序列化器?

Spring boot 动态/注解自定义 JSON 反序列化器

当值为“null”时,Jackson 忽略自定义字段反序列化器

如何在自定义反序列化器 Spring Boot 中读取路径变量或 URL 参数