使用Jackson反序列化表示String或Object的JSON有效内容

时间:2018-04-23 09:51:08

标签: java json jackson jackson-databind

我想反序列化一个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;
  }
}

有关条带java客户端的完整示例,请参阅ExpandableField

我想知道如何为杰克逊写一个JsonDeserializer<ExpandableField<?>>

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;
    }
}

我目前的解决方案是加载当前树并使用一种小方法硬编码相应的类:private Class<?> computeType(JsonNode node)

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) {
        //...
    }
}

我更喜欢更有活力的东西。

作为比较,使用 gson 库,可以在方法签名中访问该类型:

deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)

((ParameterizedType) typeOfT).getActualTypeArguments()[0]context能够使用context.deserialize(json, t)反序列化对象。

请在此处查看完整示例:ExpandableFieldDeserializer

与杰克逊有什么相似之处?

0 个答案:

没有答案