使用@JsonSubTypes反序列化没有值 - 缺少属性错误

时间:2015-01-22 13:02:56

标签: java json jackson

我像这样反序列化jsons:

{
  "type":"a",
  "payload" : {...}
}

其中有效负载类型取决于类型。我的班级:

public class Sth<T extends Payload> {

    @JsonProperty("type")
    private String type;
    @Valid
    private T payload;

    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
        property = "type",
        visible = true,
        defaultImpl = NoClass.class)
    @JsonSubTypes({
        @JsonSubTypes.Type(value = APayload.class, name = "a"),
        @JsonSubTypes.Type(value = BPayload.class, name = "b"),
        @JsonSubTypes.Type(value = CPayload.class, name = "c")})
    public void setPayload(T payload) {
    this.payload = payload;
    }

    public void setType(String type) {
    this.type = type;
    }

}

我还输入了没有有效载荷的“d”。如果我尝试反序列化:

{
  "type":"d",
  "payload" : null
}

它可以工作,但它不适用于没有负载:

{
  "type":"d",
}

如何让它与上一个例子一起使用?

我得到错误的Stacktrace:

[error] Caused by: com.fasterxml.jackson.databind.JsonMappingException: Missing property 'payload' for external type id 'type
[error]  at [Source: N/A; line: -1, column: -1]
[error]     at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
[error]     at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:700)
[error]     at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler.complete(ExternalTypeHandler.java:160)
[error]     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:690)
[error]     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:639)
[error]     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:266)
[error]     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124)
[error]     at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2965)
[error]     at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1587)
[error]     at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:1931)
[error]     at play.libs.Json.fromJson(Json.java:47)

3 个答案:

答案 0 :(得分:2)

我也遇到过这个问题,并且无法使用Jackson提供的机制(自定义BeanDeserializerBeanDeserializerModifier等)找到优雅的解决方案。

它看起来像处理外部类型ID的方式中的错误。我通过以下方式解决了这个问题:

  1. 将JSON tring反序列化为JsonNode;
  2. 如果所需的属性不存在,则手动插入null节点;
  3. JsonNode映射到我想要的值类型。
  4. 我的代码如下所示:

    public <T> T decode(String json, Class<T> type) throws IOException {
        JsonNode jsonNode = mapper.readTree(json);
    
        if (jsonNode.isObject() && (jsonNode.get("payload") == null  || jsonNode.get("payload").size() == 0)) {
            ObjectNode objectNode = (ObjectNode) jsonNode;
            objectNode.putNull("payload");
        }
    
        return mapper.treeToValue(jsonNode, type);
    }
    

答案 1 :(得分:2)

有明确的反序列化功能:


for nlines in read_n(textfile, 50):
    with open(newfile, "a") as file2:
        for item in nlines:
            file2.write(item + '\n')
    print(nlines)

答案 2 :(得分:1)

我相信我遇到了你记录的同样问题。

我收到了以下异常

com.fasterxml.jackson.databind.JsonMappingException: Missing property 'content' 
  for external type id 'contentType

我最终通过将@JsonTypeId注释添加到类型字段来实现它。

public interface Content {
}

public class Post implements Content {
  public String content = "bar";
}

public class Foo {

  @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
                include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
                property = "contentType")
  @JsonSubTypes({
    @JsonSubTypes.Type(value = Post.class, name = "post")
  })
  public Content content;

  @JsonTypeId
  public ContentType contentType;

  public enum ContentType {
    "post"
  }
}