如何使用 Java 和 Jackson 库对 Json 字符串进行多态反序列化? [英] How can I polymorphic deserialization Json String using Java and Jackson Library?

查看:31
本文介绍了如何使用 Java 和 Jackson 库对 Json 字符串进行多态反序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些类 A、B、C,它们都继承自 BaseClass.

I've some classes A, B, C they all inherit from class BaseClass.

我有一个字符串 json,其中包含 A、B、C 或 BaseClass 的 json 表示.

I've a String json that contains the json representation of the A, B, C or BaseClass.

我想用某种方法将此字符串反序列化为 BaseClass(多态反序列化).像这样

I want to have some way to deserialize this String to the BaseClass (polymorphic deserialization). Something like this

BaseClass base = ObjectMapper.readValue(jsonString, BaseClass.class);

jsonString 可以是 A、B、C 或 BaseClass 中任何一个的 Json 字符串表示.

jsonString could be Json String representation of any of A, B, C, or BaseClass.

推荐答案

不清楚原发帖人有什么问题.我猜这是两件事之一:

It's not clear what problem the original poster is having. I'm guessing that it's one of two things:

  1. 未绑定 JSON 元素的反序列化问题,因为 JSON 包含 Java 中没有任何内容可绑定的元素;或

  1. Deserialization problems with unbound JSON elements, because the JSON contains elements for which there is nothing in the Java to bind to; or

想要实现多态反序列化.

Want to implement polymorphic deserialization.

这是第一个问题的解决方案.

Here's a solution to the first problem.

import static org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES;

import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    BaseClass base = new BaseClass();
    A a = new A();
    B b = new B();
    C c = new C();

    ObjectMapper mapper = new ObjectMapper();

    String baseJson = mapper.writeValueAsString(base);
    System.out.println(baseJson); // {"baseName":"base name"}
    String aJson = mapper.writeValueAsString(a);
    System.out.println(aJson); // {"baseName":"base name","aName":"a name"}
    String bJson = mapper.writeValueAsString(b);
    System.out.println(bJson); // {"baseName":"base name","bName":"b name"}
    String cJson = mapper.writeValueAsString(c);
    System.out.println(cJson); // {"baseName":"base name","cName":"c name"}

    BaseClass baseCopy = mapper.readValue(baseJson, BaseClass.class);
    System.out.println(baseCopy); // baseName: base name

    // BaseClass aCopy = mapper.readValue(aJson, BaseClass.class);
    // throws UnrecognizedPropertyException: 
    // Unrecognized field "aName", not marked as ignorable
    // because the JSON contains elements for which no Java field
    // to bind to was provided.

    // Need to let Jackson know that not all JSON elements must be bound.
    // To resolve this, the class can be annotated with 
    // @JsonIgnoreProperties(ignoreUnknown=true) or the ObjectMapper can be
    // directly configured to not FAIL_ON_UNKNOWN_PROPERTIES
    mapper = new ObjectMapper();
    mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

    BaseClass aCopy = mapper.readValue(aJson, BaseClass.class);
    System.out.println(aCopy); // baseName: base name
    BaseClass bCopy = mapper.readValue(bJson, BaseClass.class);
    System.out.println(bCopy); // baseName: base name
    BaseClass cCopy = mapper.readValue(cJson, BaseClass.class);
    System.out.println(cCopy); // baseName: base name
  }
}

class BaseClass
{
  public String baseName = "base name";
  @Override public String toString() {return "baseName: " + baseName;}
}

class A extends BaseClass
{
  public String aName = "a name";
  @Override public String toString() {return super.toString() + ", aName: " + aName;}
}

class B extends BaseClass
{
  public String bName = "b name";
  @Override public String toString() {return super.toString() + ", bName: " + bName;}
}

class C extends BaseClass
{
  public String cName = "c name";
  @Override public String toString() {return super.toString() + ", cName: " + cName;}
}

这是第二个问题的解决方案.

Here's a solution to the second problem.

import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonSubTypes.Type;
import org.codehaus.jackson.annotate.JsonTypeInfo;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    BaseClass base = new BaseClass();
    A a = new A();
    B b = new B();
    C c = new C();

    ObjectMapper mapper = new ObjectMapper();

    String baseJson = mapper.writeValueAsString(base);
    System.out.println(baseJson); // {"type":"BaseClass","baseName":"base name"}
    String aJson = mapper.writeValueAsString(a);
    System.out.println(aJson); // {"type":"a","baseName":"base name","aName":"a name"}
    String bJson = mapper.writeValueAsString(b);
    System.out.println(bJson); // {"type":"b","baseName":"base name","bName":"b name"}
    String cJson = mapper.writeValueAsString(c);
    System.out.println(cJson); // {"type":"c","baseName":"base name","cName":"c name"}

    BaseClass baseCopy = mapper.readValue(baseJson, BaseClass.class);
    System.out.println(baseCopy); // baseName: base name
    BaseClass aCopy = mapper.readValue(aJson, BaseClass.class);
    System.out.println(aCopy); // baseName: base name, aName: a name
    BaseClass bCopy = mapper.readValue(bJson, BaseClass.class);
    System.out.println(bCopy); // baseName: base name, bName: b name
    BaseClass cCopy = mapper.readValue(cJson, BaseClass.class);
    System.out.println(cCopy); // baseName: base name, cName: c name
  }
}

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "type")  
@JsonSubTypes({  
    @Type(value = A.class, name = "a"),  
    @Type(value = B.class, name = "b"),  
    @Type(value = C.class, name = "c") }) 
class BaseClass
{
  public String baseName = "base name";
  @Override public String toString() {return "baseName: " + baseName;}
}

class A extends BaseClass
{
  public String aName = "a name";
  @Override public String toString() {return super.toString() + ", aName: " + aName;}
}

class B extends BaseClass
{
  public String bName = "b name";
  @Override public String toString() {return super.toString() + ", bName: " + bName;}
}

class C extends BaseClass
{
  public String cName = "c name";
  @Override public String toString() {return super.toString() + ", cName: " + cName;}
}

如果相反,目标是反序列化为子类类型,而没有专门用于指示子类类型的 JSON 元素,那么这也是可能的,只要可以使用 JSON 中的某些内容来决定子类是什么类型应该是.我在 http://programmerbruce 上发布了一个这种方法的例子.blogspot.com/2011/05/deserialize-json-with-jackson-into.html.

If instead, the goal is to deserialize to a subclass type without a JSON element specifically dedicated to indicate what the subclass type is, then that is also possible, so long as something in the JSON can be used to decide what the subclass type should be. I posted an example of this approach at http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html.

这篇关于如何使用 Java 和 Jackson 库对 Json 字符串进行多态反序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆