Tweak jackson多态反序列化

时间:2016-05-27 13:19:14

标签: jackson deserialization

我有一个像这样的简单多态模型

public class Foo {

    private Bar bar1;

    private Bar bar2;

    public Bar getBar1() {
        return bar1;
    }

    public Bar getBar2() {
        return bar2;
    }

    public void setBar1(Bar bar1) {
        this.bar1 = bar1;
    }

    public void setBar2(Bar bar2) {
        this.bar2 = bar2;
    }

}

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type")
public class Bar {

}


public class BarExpression extends Bar {

    private String expression;

    public String getExpression() {
        return expression;
    }

    @JsonIgnore
    public Object getValue() {
        return null;
    }

    public void setExpression(String expression) {
        this.expression = expression;
    }
}

public class BarLiteral extends Bar {

    private String value;

    private String type;

    public String getType() {
        return type;
    }

    public Object getValue() {
        return value;
    }

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

    public void setValue(String value) {
        this.value = value;
    }

}

序列化一个这样的简单例子

public void run() throws Exception {
    Foo foo;
    BarLiteral bar1;
    BarExpression bar2;
    //
    foo = new Foo();
    bar1 = new BarLiteral();
    bar1.setType("java.lang.String");
    bar1.setValue("gnu");
    foo.setBar1(bar1);
    bar2 = new BarExpression();
    bar2.setExpression("bean.property * 2");
    foo.setBar2(bar2);
    //
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);
    StringWriter w = new StringWriter();
    mapper.writeValue(w, foo);
    System.out.println(w.toString());
}

给出了预期的结果:

{
  "bar1" : {
    "@type" : "de.mit.jackson.BarLiteral",
    "value" : "gnu",
    "type" : "java.lang.String"
  },
  "bar2" : {
    "@type" : "de.mit.jackson.BarExpression",
    "expression" : "bean.property * 2"
  }
}

现在的问题是:我希望在手写这个" DSL"通过支持"原始捷径"对于键入的" Bar ..."像这样的课程

{
  "bar1" : "gnu",
  "bar2" : "@{bean.property * 2}"
}

最接近的解决方案是在Foo#bar1和Foo#bar2上使用转换器,检查String或" Bar"输入,但这个解决方案需要装饰每个属性定义。

创建具有类似行为的反序列化器不起作用,因为@JsonTypeInfo不兼容,因为我可以使用@JsonDeserialize实现来检查String事件,然后委托给标准的@JsonTypeInfo进程。 @JsonTypeInfo标准将仅检查@type,然后委托回(子类型)反序列化器,这也是我的包装器实现。

所需的流程是

if input event is string {
   parse and return string input
} else {
   activate @type parsing delegate;
   after @type parsing activate standard BeanDeserializer 
   (**not** my implementation)
}

我缺少另一个钩子吗?

0 个答案:

没有答案