【问题标题】:Asymmetric serialization and deserialization using Jackson使用 Jackson 的非对称序列化和反序列化
【发布时间】:2015-05-08 23:31:33
【问题描述】:

我正在使用 Jackson 为 RESTful API 序列化和反序列化数据。我想要一个 REST 资源 (/comments),它允许发布 cmets 以及获取 cmets 列表。

这是发布到 /comments 的(简化的)示例。

{"text":"Text","author":"Paul","email":"paul@example.org"}

GET /comments 的结果如下所示:

[{"text":"Text","author":"Paul","emailHash":"76w0kjKP9HpsdhBjx895Sg=="}]

由于电子邮件地址不应该对任何人可见,因此我决定在回复中仅返回电子邮件地址的 MD5 哈希值。

我创建了一个简单的 POJO 类 Comment,其中包含用于 textauthoremailemailHash 的 getter 和 setter 字段。

现在,当我序列化结果时,我得到如下:

[{"text":"Text","author":"Paul","email":null,"emailHash":"76w0kjKP9HpsdhBjx895Sg=="}]

但我真的不喜欢 email 在此处返回为 null。根本不应该包含它。

在该字段上使用注释 @JsonIgnore 也会在反序列化时忽略它。我是否必须创建两个类,例如 CreationCommentResultComment 以及共享公共字段的超类 Comment,还是有办法避免创建额外的类?

【问题讨论】:

  • 只是忽略空值是一种选择吗?
  • @chrylis 你的意思是,就像忽略返回的 JSON 中的所有空值?不,很遗憾没有。 "emailHash" 也可以为 null,应按原样返回。

标签: java json serialization jackson


【解决方案1】:

您根本不必创建 2 个类。使用 Jackson,您可以使用注释在序列化和反序列化期间完全控制属性的行为,在 getter 中使用 @JsonIgnore 可以防止属性在 Json 响应中被序列化,并在 setter 中使用 @JsonProperty 注释,属性将是在反序列化期间设置。代码将如下所示:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Comment {

    private String author;

    private String email;

    @JsonIgnore
    public String getEmail() {
        return email;
    }

    @JsonProperty
    public void setEmail(String email) {
        this.email = email;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();

        Comment comment = new Comment();
        comment.setAuthor("anAuthor");
        comment.setEmail("email@example.com");

        try {
            System.out.println(objectMapper.writeValueAsString(comment));

            String json = "{\"author\":\"anAuthor\",\"email\":\"another@email.com\"}";
            Comment fromJson = objectMapper.readValue(json, Comment.class);

            System.out.println("Result from Json: author= " + fromJson.getAuthor() + ", email= " + fromJson.getEmail());

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

运行main()方法测试解决方案后的输出:

{"author":"anAuthor"}

Result from Json: author= anAuthor, email= another@email.com

希望对你有帮助,

何塞·路易斯

【讨论】:

  • +1 这正是我想要的!我不知道@JsonProperty 有点“压倒性”@JsonIgnore
【解决方案2】:

您可以将@JsonIgnore 放在getEmail 上以防止它被序列化为JSON,并使用@JsonCreator 向Jackson 指示用于反序列化的构造函数。然后,构造函数将只接受 email 属性,并将散列并分配给您的 emailHash 字段。

您可以在 Comment 类上添加 @JsonInclude 注释,以防止 null 字段的序列化。

你的班级最终可能会是这样的:

@JsonInclude(Include.NON_NULL)
public class Comment {
    private final String email;
    private final String emailHash;

    @JsonCreator
    public Comment(@JsonProperty("email") String email) {
        this.email = email;
        this.emailHash = MD5.hash(email);
    }

    @JsonIgnore
    public String getEmail() {
        return email;
    }

    public String getEmailHash() {
        return emailHash;
    }
}

【讨论】:

  • +1 感谢您的回答。这个解决方案有效,但我更喜欢@jbarrueta 的答案,因为它不需要额外的构造函数。
猜你喜欢
  • 2014-07-27
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
  • 2019-10-25
  • 2015-01-05
  • 2020-07-07
  • 1970-01-01
  • 2017-11-29
相关资源
最近更新 更多