2013-01-08 45 views
10

我有一個樣本類:的EclipseLink莫西JSON序列化

class Zoo { 
    public Collection<? extends Animal> animals; 
} 

當系列化與莫西,我得到:

{ 
    "bird": [ 
     { 
      "name": "bird-1", 
      "wingSpan": "6 feets", 
      "preferredFood": "food-1" 
     } 
    ], 
    "cat": [ 
     { 
      "name": "cat-1", 
      "favoriteToy": "toy-1" 
     } 
    ], 
    "dog": [ 
     { 
      "name": "dog-1", 
      "breed": "bread-1", 
      "leashColor": "black" 
     } 
    ] 
} 

爲什麼使用它陣列指標 「[]」,而鳥,貓和狗不是數組? 其次,有沒有辦法擺脫「鳥」,「貓」和「狗」?

換句話說,我試圖去:

{ 
     { 
      "name": "bird-1", 
      "wingSpan": "6 feets", 
      "preferredFood": "food-1" 
     } 
    , 
     { 
      "name": "cat-1", 
      "favoriteToy": "toy-1" 
     } 
    , 
     { 
      "name": "dog-1", 
      "breed": "bread-1", 
      "leashColor": "black" 
     } 
} 

感謝, Behzad

回答

9

問題#1

爲什麼使用數組的指標是「[] 「,而鳥,貓和狗都是 不是數組?

爲了讓您映射與@XmlElementRef註釋,它告訴JAXB使用@XmlRootElement標註爲繼承指標的數值模型這個JSON表示。隨着MOXy的JSON綁定,這些成爲關鍵。我們使這些鍵JSON數組的值成爲可能,因爲不允許重複鍵。

動物園

在模型中你有你的animals字段/屬性的@XmlElementRef註解。

import java.util.Collection; 
import javax.xml.bind.annotation.XmlElementRef; 

class Zoo { 
    @XmlElementRef 
    public Collection<? extends Animal> animals; 
} 

動物

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({Bird.class, Cat.class, Dog.class}) 
public abstract class Animal { 

    private String name; 

} 

在每個子類中你有一個@XmlRootElement註解。

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Bird extends Animal { 

    private String wingSpan; 
    private String preferredFood; 

} 

input.json /輸出

{ 
    "bird" : [ { 
     "name" : "bird-1", 
     "wingSpan" : "6 feets", 
     "preferredFood" : "food-1" 
    } ], 
    "cat" : [ { 
     "name" : "cat-1", 
     "favoriteToy" : "toy-1" 
    } ], 
    "dog" : [ { 
     "name" : "dog-1", 
     "breed" : "bread-1", 
     "leashColor" : "black" 
    } ] 
} 

更多信息


問題2

其次,有沒有擺脫 「鳥」, 「貓」 和 「狗」 的一種方式?

您將需要某種繼承指示器來表示各種子類。

選項1 - @XmlDescriminatorNode/@XmlDescriminatorValue

在這裏,我做到這一點使用莫西的@XmlDescriminatorNode/@XmlDescriminatorValue註釋。

動物園

import java.util.Collection; 

class Zoo { 
    public Collection<? extends Animal> animals; 
} 

動物

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({Bird.class, Cat.class, Dog.class}) 
@XmlDiscriminatorNode("@type") 
public abstract class Animal { 

    private String name; 

} 

import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; 

@XmlDiscriminatorValue("bird") 
public class Bird extends Animal { 

    private String wingSpan; 
    private String preferredFood; 

} 

input.json /輸出

{ 
    "animals" : [ { 
     "type" : "bird", 
     "name" : "bird-1", 
     "wingSpan" : "6 feets", 
     "preferredFood" : "food-1" 
    }, { 
     "type" : "cat", 
     "name" : "cat-1", 
     "favoriteToy" : "toy-1" 
    }, { 
     "type" : "dog", 
     "name" : "dog-1", 
     "breed" : "bread-1", 
     "leashColor" : "black" 
    } ] 
} 

更多信息

選項#2 - @XmlClassExtractor

ClassExtractor(AnimalExtractor)

您可以編寫一些代碼,根據JSON內容確定適當的子類。

import org.eclipse.persistence.descriptors.ClassExtractor; 
import org.eclipse.persistence.sessions.*; 

public class AnimalExtractor extends ClassExtractor { 

    @Override 
    public Class extractClassFromRow(Record record, Session session) { 
     if(null != record.get("@wingSpan") || null != record.get("@preferredFood")) { 
      return Bird.class; 
     } else if(null != record.get("@favoriteToy")) { 
      return Cat.class; 
     } else { 
      return Dog.class; 
     } 
    } 

} 

動物

@XmlClassExtractor註釋用於指定ClassExtractor

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlClassExtractor; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({Bird.class, Cat.class, Dog.class}) 
@XmlClassExtractor(AnimalExtractor.class) 
public abstract class Animal { 

    private String name; 

} 

由於莫西如何處理@XmlElement@XmlAttribute註解,任何您想要的數據將被提供給ClassExtractor將需要與@XmlAttribute進行註釋。

import javax.xml.bind.annotation.XmlAttribute; 

public class Bird extends Animal { 

    @XmlAttribute 
    private String wingSpan; 

    @XmlAttribute 
    private String preferredFood; 

} 

輸入。JSON /輸出

{ 
    "animals" : [ { 
     "wingSpan" : "6 feets", 
     "preferredFood" : "food-1", 
     "name" : "bird-1" 
    }, { 
     "favoriteToy" : "toy-1", 
     "name" : "cat-1" 
    }, { 
     "breed" : "bread-1", 
     "leashColor" : "black", 
     "name" : "dog-1" 
    } ] 
} 

更多信息


DEMO CODE

以下演示代碼可與上述兩種映射一起使用。

import java.util.*; 
import javax.xml.bind.*; 
import javax.xml.transform.stream.StreamSource; 
import org.eclipse.persistence.jaxb.JAXBContextProperties; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     Map<String, Object> properties = new HashMap<String, Object>(); 
     properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); 
     properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); 
     JAXBContext jc = JAXBContext.newInstance(new Class[] {Zoo.class}, properties); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     StreamSource json = new StreamSource("src/forum14210676/input.json"); 
     Zoo zoo = unmarshaller.unmarshal(json, Zoo.class).getValue(); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(zoo, System.out); 
    } 

} 
+1

非常感謝您的回覆。 –

+0

非常感謝您的回覆。我在反序列化過程中遇到異常。我無法更新帖子。我已經添加了這個信息作爲答案。謝謝你的幫助! –

+0

@BehzadPirvali - 您可以將您看到的問題作爲新問題發佈嗎? –