【问题标题】:Deseralize polymorphic JSON string反序列化多态 JSON 字符串
【发布时间】:2019-09-11 15:22:40
【问题描述】:

我有几个 POJO,它们都具有相同的抽象基类。我想在不进行类型检查或强制转换的情况下进行序列化和反序列化。

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.WRAPPER_OBJECT,
    property = "type"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = UserEvent.class, name = "user"),
        @JsonSubTypes.Type(value = SystemEvent.class, name = "system")
})
public abstract class Event {
    private Long id;
    private Date date;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}

@JsonTypeName("user")
public class UserEvent extends Event {

    private String userId;
    private String userName;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

@JsonTypeName("system")
public class SystemEvent extends Event {

    private String source;

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }
}

当我将 UserEvent 序列化为 JSON 时,我得到以下输出,类型名称为包装对象。

{
  "user" : {
    "id" : 42,
    "date" : 1568214606656,
    "userId" : "123123",
    "userName" : "Bob"
  }
}

到目前为止一切顺利。如果我尝试反序列化相同的 JSON 对象,它会失败。

@Test
void deserializeUserEvent() throws Exception {
    String json =
            "\"user\" : {\n" +
            "    \"id\" : 42,\n" +
            "    \"date\" : 1568211488351,\n" +
            "    \"userId\" : \"123123\",\n" +
            "    \"userName\" : \"Bob\"\n" +
            "  }";

    ObjectMapper mapper = new ObjectMapper();
    Event event = mapper
            .readerFor(Event.class)
            .readValue(json); // ERROR

    assertSame(UserEvent.class, event.getClass());
}

是否可以通过只声明抽象类型来反序列化具体类型?

【问题讨论】:

    标签: java json serialization jackson deserialization


    【解决方案1】:

    是的,您可以使用它。我在这里使用对象映射器将您的对象写为字符串。

        UserEvent ue = new UserEvent();
        ue.setUserName("Some Username");
        ue.setUserId("userID");
        ue.setDate(new Date());
        ue.setId(123123L);
        ObjectMapper objectMapper = new ObjectMapper();
        String userEventString = objectMapper.writeValueAsString(ue);
    

    {"user":{"id":123123,"date":1568217548148,"userId":"userID","userName":"asdlasd"}}

    并将其读作:

    Event event = objectMapper.readValue(userEventString, Event.class);
    

    ObjectMapper 也让你可以使用:

    ObjectMapper mapperWithMixin = new ObjectMapper()
            .addMixIn(Event.class, UserEvent.class);
    

    其中 Event.class 是您的目标类,而 UserEvent.class 是您提供的 json 对象。

    【讨论】:

      【解决方案2】:

      是的,可以通过只声明抽象类型来反序列化具体类型。

      要反序列化的字符串应该是正确的 JSON。

      String json = "{\"user\":{\"id\":42,\"date\":1568216805617,\"userId\":\"123123\",\"userName\":\"Bob\"}}";
      Event event = mapper.readValue(json, Event.class);
      

      以上代码适用于最新版本的 jackson-databind - 2.9.9.3

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-02
        • 2013-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多