为Jackson Mapper提供了多种方法来反序列化同一个对象

时间:2014-02-14 22:36:55

标签: jackson

我正在尝试反序列化两种类型的json:

{
    name: "bob",
    worksAt: {
        name: "Bobs department store",
        location: "downtown"
    },
    age: 46
}

{
    name: "Tom",
    worksAt: "company:Bobs department store",
    age: 27
}

进入这些对象:

UML of classes

第一种方法创建两个新对象,第二种方式根据字符串的内容从数据库中请求对象。

有点像杰克逊映射器如何将任意字符串反序列化为对象,对于像这样的对象:

public class Company{
    public String name;
    public Employee[] employees
    public Company(){}
    public Company(String json){
        //turn string into object using whatever encoding you want blah blah blah...
    }
}

问题是我需要两者。我需要它来处理对象和字符串。两者都可以从相同的输入到达。

我试过的第一个想法是制作转换器

它表示这些会创建一个委托类型以传递给反序列化器,但即使数据类型不是字符串,也始终应用转换器。所以这不起作用。

我也试过一个普通的反序列化器,但我找不到一种方法来推迟BeanDeserializer。 beanDeserializer非常复杂,我无法手动实例化它。我也看不到推迟使用jackson mapper中的默认反序列化器。

我是否必须重新实现jackson mappers反序列化才能执行此操作?解串器有没有办法说“我不能这样做,使用默认实现。”?

编辑:进一步的进展。基于Jackson Mapper源代码,看起来你可以像这样实例化bean反序列化器:

DeserializationConfig config = ctxt.getConfig();
JavaType type = config.constructType(_valueClass);
BeanDescription introspect = config.introspect(type);
JsonDeserializer<Object> beanDeserializer = ctxt.getFactory().createBeanDeserializer(ctxt, type , introspect);

但由于某种原因,所有_beanProperties都为其_valueDeserializer设置了FailingDeserializer,整个过程失败了。所以我不知道为什么会这样......

3 个答案:

答案 0 :(得分:2)

你试过writing a custom deserializer吗?这使您可以最大程度地控制杰克逊如何反序列化对象。您可以尝试单向反序列化,如果出现错误,请尝试其他方式。

杰克逊也可以处理polymorphic deserialization,虽然这需要对json进行少量更改以包含类型信息,听起来你的问题限制可能不允许这样做。

答案 1 :(得分:1)

如果我正确理解了问题,我建议使用JsonNode。您可以在顶级类型中定义一个setter,如下所示:

setWorksAt(JsonNode node) {
    if (node.getNodeType == JsonNodeType.STRING) {
        String name = node.getText();
        name = name.substring(name.lastIndexOf(':'));
        this.company = new Company(name);
    } else if (node.getNodeType == JsonNodeType.OBJECT) {
        this.company = mapper.treeToValue(node, Company.class);
    }
}

这允许您处理两个单独的worksFor输入,同时仍允许标准映射器处理OBJECT案例的任何子结构。

答案 2 :(得分:0)

最新版本的Jackson(我认为2.8+,绝对可以使用2.9)你可以使用多个@JsonCreator并执行以下操作:

public class Company {
    private String name;
    private String location;

    private Company(String name, String location) {
        this.name = name;
        this.location = location;
    }
    private Company(String stringRepresentation) {
       // add code here to parse string and extract name and location
    }

    @JsonCreator
    private static Company fromJson(
            @JsonProperty("name") String name,
            @JsonProperty("location") String location)
    {
        return new Company(name, location);
    }

    @JsonCreator
    private static Company fromJson(String str) {
        return Company(str);
    }
}