2011-07-01 14 views
24

私はいくつかのクラスA、B、Cを持っています。それらはすべてBaseClassクラスから継承しています。JavaとJacksonライブラリを使用してJson Stringをどのように多面体逆シリアル化できますか?

私は、A、B、CまたはBaseClassのjson表現を含むString jsonを持っています。

このStringをBaseClassに逆シリアル化する方法(多態的な逆シリアル化)が必要です。この

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

jsonStringようなものは、A、B、C、またはBaseClassの任意のJSON文字列表現であってもよいです。

答えて

40

これは、元のポスターを持っているものの問題は明らかではありません。私はそれが2つのうちの1つだと推測している:JSONがバインドするためのJavaで何もないそのための要素が含まれているため、未結合のJSON要素と

  1. デシリアライズの問題。または

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

ここに2番目の問題の解決方法があります。

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に掲載しました。

+2

あなたはちょうどその場に出ました。それは私が懸念している第二の問題です。ありがとうございました! – mohamede1945

+0

申し訳ありませんが、私は十分に明確ではありませんでした。私は私の心配を反映するために質問を編集しました。 – mohamede1945

+0

私は実際に問題#1への解決策を探していました - FAIL_ON_UNKNOWN_PROPERTIES == falseは私が必要としていたものでした:) – pedorro

2

GoogleのGsonライブラリを見ましたか?私はそれがあなたが探していることをすると思います。

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

+0

私は自分のプロジェクトでgsonを使用しました。それは良いと簡単だった。 – Bohemian

+1

実際には、Jackson Libraryを使用する必要があります。 – mohamede1945

+2

Gsonの現在のリリースには、多態的な直列化を処理する組み込みのメカニズムがありません。次のリリースは、この機能を持つように見えます。 –

関連する問題