【问题标题】:JSON Deserialization from ID into Object从 ID 到 Object 的 JSON 反序列化
【发布时间】:2016-11-21 10:23:09
【问题描述】:

为了确保在我的 RESTful Web 服务中来回发送的数据不是多余的,每个嵌套对象都只有它的 ID 序列化(MessageUser 创建者只有 userId 序列化,因为两者客户端和服务器已经知道用户的所有详细信息)。

序列化工作完美,产生这个:

{"messageCreatorUser":"60d01602-c04d-4a3f-bbf2-132eb0ebbfc6","messageBody":"Body", ...}

问题:反序列化不会生成只有其 ID 的嵌套对象。生成的反序列化嵌套对象为 null。

这里是前面提到的MessageUser 对象。序列化“策略”是从此处指定的第三个选项中使用的:How to serialize only the ID of a child with Jackson

Message.java

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "messageId")
public class Message implements Serializable {

    // -- Hibernate definitions omitted --
    private UUID messageId;

    // -----------------------------------------------------------------
    // Here is what makes the serializer print out the ID specified on the class definition

    @JsonIdentityReference(alwaysAsId = true)

    // Here is my attempt to get the User class back when I deserialize

    @JsonDeserialize(as = User.class)
    @JsonSerialize(as = User.class)

    private User messageCreatorUser;
    // ------------------------------------------------------------------


    // -- more arbitrary properties --

    public Message() {
    }

    public Message(UUID messageId) {
        this.messageId = messageId;
    }

    public Message(String messageId) {
        this.messageId = UUID.fromString(messageId);
    }

    // -- getters and setters --

User.java

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "userId")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User implements Serializable {

    private UUID userId;

    // -- other arbitrary properties -- 

    public User() {
    }

    public User(UUID userId) {
        this.userId = userId;
    }

    public User(String userId) {
        this.userId = UUID.fromString(userId);
    }

    // -- getters and setters --

预期的反序列化对象:

Message object =
     String messageBody = "Body";
     User messageCreatorUser =
         UUID userId = 60d01602-c04d-4a3f-bbf2-132eb0ebbfc6;

实际反序列化对象:

Message object =
     String messageBody = "Body";
     User messageCreatorUser = null;

就像我说的,我希望创建一个嵌套的 User 对象,其 ID 仅为 60d01602-c04d-4a3f-bbf2-132eb0ebbfc6

使用:

  • Wildfly 10.0.Final:
    • RESTEasy 3.0.15.Final
    • RESTEasy Jackson 2 提供程序 3.0.15.Final
      • Jackson 2.6.3(注解、核心、数据绑定等)

为什么结果不同?

【问题讨论】:

    标签: java json serialization jackson


    【解决方案1】:

    正如这里的答案 (Jackson deserialize JsonIdentityReference (alwaysAsId = true)) 所说,使用 setter 反序列化器效果很好,并且不需要令人讨厌的自定义反序列化器:

    Message.java

        @JsonInclude(JsonInclude.Include.NON_NULL)
        @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "messageId")
        public class Message implements Serializable {
    
            private UUID messageId;
    
            @JsonIdentityReference(alwaysAsId = true)
            private User messageCreatorUser;
    
            // -- other fields and such --
    
            public User getMessageCreatorUser() {
                return messageCreatorUser;
            }
    
            public void setMessageCreatorUser(User messageCreatorUser) {
                this.messageCreatorUser = messageCreatorUser;
            }
    
            @JsonProperty("messageCreatorUser")
            public void setMessageCreatorUser(String userId) {
                this.messageCreatorUser = new User(userId);
            }
    

    User.java

        @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "userId")
        public class User implements Serializable {
    
            private UUID userId;
    
            // -- other fields --
    
            public User(String userId) {
                this.userId = UUID.fromString(userId);
            }
    
        }
    

    请注意,要使用@JsonIdentityReference(alwaysAsId = true),您需要在某处拥有@JsonIdentityInfo(...)

    【讨论】:

      【解决方案2】:

      不确定我是否了解整个情况,但如果您只想强制序列化为 id,您可以使用:

       @JsonIdentityReference(alwaysAsId=true)
      

      请记住,反序列化确实需要某种方法将该 id 解析回实例,这通常意味着实际的完整 Object 应该通过其他一些属性引用进行序列化。

      【讨论】:

      • 我会澄清我使用的注释。我有 @JsonIdentityReference(alwaysAsId=true)@Json(De)Serialize(as = User.class) 希望它能够创建 bean。
      • 强制序列化作为 id 是否绝对需要在 JSON 中返回被引用的对象?也许我可以让序列化程序用 ID 制作空的 User 对象并将其附加?
      • 不是强制的,所以绝对只能使用id,不需要占位符Object。但是如果读回数据,你必须能够以某种方式取回数据——这可能没问题,只是想提一下,因为它可能会在某些用例中出现问题。
      • 是的,当你制作客户端时,你必须牢记不断向服务器查询完整数据。
      • 我怎样才能使这项工作仅适用于嵌入式对象 - 这是我的问题:stackoverflow.com/questions/46620019/…
      猜你喜欢
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 1970-01-01
      • 2019-06-19
      • 2020-07-22
      相关资源
      最近更新 更多