简体   繁体   English

使用基于JSON类型的Jackson进行反序列化

[英]Deserializing using Jackson based on JSON type

I have a JSON payload I am attempting to deserialize using Jackson that looks like: 我有一个JSON有效负载,我试图使用Jackson反序列化,看起来像:

{
  "id": "12",
  "type": "foo",
  "created": "2011-03-20T31:12:00+00:00",
  "data": {
    "object": {
        objectId: 1
        fizz: "bizz"
    }
}

There are 3 different "type" responses possible {foo, bar, foobar} and, depending on which type is in the payload, the "object" node will have different data underneath it (type foo has fizz for example). 有3种不同的“类型”响应可能{foo, bar, foobar}并且根据有效负载中的哪种类型, "object"节点下面会有不同的数据(例如foo类型有fizz)。 I am attempting to write some deserializers that will detect the type, and output a class containing the contents of "object" . 我试图编写一些将检测类型的反序列化器,并输出一个包含"object"内容的class I can basically ignore the id and created fields. 我基本上可以忽略id和创建的字段。 The types of classes are as follows: 类的类型如下:

public interface ObjectType {
   String getId()
}

public class Foo implements ObjectType {
   String objectId;
   String fizz;

   String getId() {
      return objectId;
   }
}

public class Bar implements ObjectType {
   String objectId;
   String test;

   String getId() {
      return objectId;
   }
}

public class FooBar implements ObjectType {
   String objectId;
   String something;

   String getId() {
      return objectId;
   }
}

What is the simplest way to do so in Jackson? 杰克逊最简单的方法是什么?

One possibility is to write a custom deserializer. 一种可能性是编写自定义反序列化器。 A stub implementation could be as follows: 存根实现可以如下:

class ContainerDeserializer extends StdDeserializer<Container> {

    private static final long serialVersionUID = 8976140492203602443L;

    public ContainerDeserializer() {
        this(null);
    }

    public ContainerDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Container deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        int id = (Integer) ((IntNode) node.get("id")).numberValue();
        String type = node.get("type").asText();
        ObjectType obj;
        String objId = node.get("obj").get("objectId").asText();
        switch (type) {
        case "foo":
            String fizz = node.get("obj").get("fizz").asText();
            obj = new Foo(objId, fizz);
            break;
        case "bar":
            String test = node.get("obj").get("test").asText();
            obj = new Bar(objId, test);
            break;
        default:
            // Error handling
            obj = null;

        }

        return new Container(id, type, obj);
    }
}

For the implementation I assumed you have the following Container class: 对于实现,我假设您有以下Container类:

class Container {
    private String type;
    private int id;
    private ObjectType obj;

    public Container(int id, String type, ObjectType obj) {
        this.id = id;
        this.type = type;
        this.obj = obj;
    }

    public String getType() {
        return type;
    }

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

    public ObjectType getObj() {
        return obj;
    }

    public void setObj(ObjectType obj) {
        this.obj = obj;
    }

    public int getId() {
        return id;
    }

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

}

I also added getters and setters to your Foo and Bar classes. 我还为你的Foo和Bar课程添加了getter和setter。

Now just register the Deserializer with 现在只需注册Deserializer

ObjectMapper om = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Container.class, new ContainerDeserializer());
om.registerModule(module);

and deserialize using 并使用反序列化

om.readValue(test, Container.class);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM