Java 使用Jackson反序列化表示字符串或对象的JSON负载

Java 使用Jackson反序列化表示字符串或对象的JSON负载,java,json,jackson,jackson-databind,Java,Json,Jackson,Jackson Databind,我想反序列化一个JSON负载,该负载表示可以是字符串(未展开)或对象(展开)的字段: 示例有效负载未展开的:仅发送表示包含id的字符串值 { "id" : "777424881071", "category" : "/category/12", "title" : "ACADEMY DINOSAUR", "description" : "A Epic Drama of ...", } 示例有效负载已扩展:发送相应的id: { "id" : "777424881071",

我想反序列化一个JSON负载,该负载表示可以是字符串(未展开)或对象(展开)的字段:

示例有效负载未展开的:仅发送表示包含id的字符串值

{
  "id" : "777424881071",
  "category" : "/category/12",
  "title" : "ACADEMY DINOSAUR",
  "description" : "A Epic Drama of ...",
  }
示例有效负载已扩展:发送相应的id:

{
  "id" : "777424881071",
  "category" : {
    "id" : "12",
    "name" : "Children"
  },
  "title" : "ACADEMY DINOSAUR",
  "description" : "A Epic Drama of ...",
  }
在java中,这可以用如下类型表示:

public class ExpandableField<T> {
  private String id;
  private T expandedObject;

  public ExpandableField(String id, T expandedObject) {
    this.id = id;
    this.expandedObject = expandedObject;
  }
}
使用
((ParameterizedType)typeOfT).getActualTypeArguments()[0]
上下文可以使用
上下文反序列化对象。反序列化(json,t)

请参见此处的完整示例:



杰克逊怎么能做出类似的事情来?

你要求的是类似于“鸭子打字”的事情吗?就像这里问的那样?我们还发现:“我们希望我们的反序列化程序自动为我们实例化正确的类型”
public class ExpandableFieldDeserializer extends JsonDeserializer<ExpandableField<?>> {

    @Override
    public ExpandableField<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken token = p.getCurrentToken();
        if (token == JsonToken.VALUE_STRING) {
            return new ExpandableField<>(p.getValueAsString(), null);
        }
        else if (token == JsonToken.START_OBJECT) {
            //TODO deserialize object and compute id
            return new ExpandableField<>(id, object);
        }
        return null;
    }
}
public class ExpandableFieldDeserializer extends JsonDeserializer<ExpandableField<?>> {

    @Override
    public ExpandableField<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken token = p.getCurrentToken();
        if (token == JsonToken.VALUE_STRING) {
            return new ExpandableField<>(p.getValueAsString(), null);
        }
        else if (token == JsonToken.START_OBJECT) {
            ObjectCodec codec = p.getCodec();
            JsonNode node = codec.readTree(p);
            String id = null;
            if (node.has("id")) {
                id = node.asText();
            }
            Class<?> typeClass = computeType(node);
            Object object = codec.treeToValue(node, typeClass);
            return new ExpandableField<>(id, object);
        }
        return null;
    }

    private Class<?> computeType(JsonNode node) {
        //...
    }
}
deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)