簡體   English   中英

如何使用Java和Jackson Library對Json String進行多態反序列化?

[英]How can I polymorphic deserialization Json String using Java and Jackson Library?

我有一些類A,B,C它們都繼承自BaseClass類。

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

我想有一些方法將此String反序列化為BaseClass(多態反序列化)。 像這樣的東西

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

jsonString可以是A,B,C或BaseClass中的任何一個的Json String表示。

目前尚不清楚原始海報有什么問題。 我猜這是兩件事之一:

  1. 未綁定的JSON元素的反序列化問題,因為JSON包含要綁定到Java中的任何內容的元素; 要么

  2. 想要實現多態反序列化。

這是第一個問題的解決方案。

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;}
}

這是第二個問題的解決方案。

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上發布了這種方法的示例。

你看過谷歌的Gson圖書館嗎? 我認為它可以滿足您的需求。

http://code.google.com/p/google-gson/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM