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

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

问题描述

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

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

我有一个包含A的json表示的String json, B,C或BaseClass。

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

我想有一些方法将这个String反序列化为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 可以是任何Json String表示A,B,C或BaseClass。

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 Library对Json String进行多态反序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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