2012-02-29 50 views
1

私はJAXBを学習する過程にあり、いくつかのアダプターを試してみたかったのです。非常にシンプルなクラスに1つ追加したときに、JAXBContext.newInstance()呼び出しでNullPointerExceptionがスローされました。アダプタは厳密には必要ではないことに注意してください。 @XmlJavaTypeAdapter(MapTypeAdaptor.class)注釈をコメントアウトすると、コードが機能します。しかしそれは私がアダプターの使い方を学ぶのを助けません... MapType.classとMapTypeEntry.classをJAXBContext.getInstance()に追加しても問題は解決されませんでした。XMLAdapterを追加すると、JAXBContext.newInstanceメソッドでNullPointerExceptionが発生する

私が間違っていることに関するアドバイスを本当にありがとうと思います。ありがとう!

は、ここで私がマーシャリングしていたJavaオブジェクトの:

import java.util.List; 
import java.util.Map; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import com.s5a.api.models.jaxb.MapTypeAdaptor; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement 
public class TestCollections { 

@XmlJavaTypeAdapter(MapTypeAdaptor.class) // <---Adding this line causes the error 
private Map<String, Object> oneColor; 
public Map<String, Object> getColor() { 
    return oneColor; 
} 
public void setColor(Map<String, Object> oneColor) { 
    this.oneColor = oneColor; 
} 

public List<String> getListOfColors() { 
    return listOfColors; 
} 

public void setListOfColors(List<String> listOfColors) { 
    this.listOfColors = listOfColors; 
} 

private List<String> listOfColors; 


} 

はここアダプタです:

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Map.Entry; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class MapTypeAdaptor extends XmlAdapter<MapType, Map<String, Object>> { 

@Override 
public MapType marshal(Map<String, Object> map) throws Exception { 
    ArrayList<MapEntryType> entries = new ArrayList<MapEntryType>(); 
    MapType mapType = new MapType(); 
    if (map != null && map.entrySet() != null){ 
     for (Entry<String, Object> entry : map.entrySet()) { 
      MapEntryType mapEntryType = new MapEntryType(); 
      if (entry != null){ 
       mapEntryType.setKey(entry.getKey()); 
       mapEntryType.setValue(entry.getValue()); 
      } 
      entries.add(mapEntryType); 
     } 
     mapType.setEntries(entries); 
    } 
    return mapType; 
} 

@Override 
public Map<String, Object> unmarshal(MapType map) throws Exception { 
    HashMap<String, Object> hashMap = new HashMap<String, Object>(); 
    if (map != null){ 
     for (MapEntryType entryType : map.getEntries()) { 
      if (entryType != null){ 
       hashMap.put(entryType.getKey(), entryType.getValue()); 
      } 
     } 
    } 
    return hashMap; 
} 
} 

は、ここでのMapTypeクラスです:

import java.util.ArrayList; 
import java.util.List; 

public class MapType { 

private List<MapEntryType> mapEntries = new ArrayList<MapEntryType>(); 

public List<MapEntryType> getEntries() { 
    return mapEntries; 
} 

public void setEntries(List<MapEntryType> mapEntries) { 
    this.mapEntries = mapEntries; 
} 
} 

そして、ここではMapEntryTypeクラスです:

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlValue; 

@XmlAccessorType(XmlAccessType.FIELD) 
public class MapEntryType { 

@XmlAttribute 
private String key; 
@XmlValue 
private Object value; 

public String getKey() { 
    return key; 
} 

public void setKey(String key) { 
    this.key = key; 
} 

public Object getValue() { 
    return value; 
} 

public void setValue(Object value) { 
    this.value = value; 
} 
} 

最後に、私のユニットテストは:

@XmlAttribute 
private String key; 
@XmlValue 
private Object value; 

へ:あなたがオブジェクトの値を格納する必要があると若干異なるXML出力を受け入れて喜んでいる場合

@Test 
    public void shouldReturnXMLRepresentation() throws Exception { 

    TestCollections test = new TestCollections(); 
    HashMap<String, Object> color1 = new HashMap<String, Object>(); 
    color1.put("blue", new Integer(50)); 
    HashMap<String, Object> color2 = new HashMap<String, Object>(); 
    color2.put("red", "red is the 2nd color"); 
    ArrayList<Map<String, Object>> colors = new ArrayList<Map<String, Object>>(); 
    colors.add(color1); 
    colors.add(color2); 
    test.setColor(color1); 

    ArrayList<String> listofstrings = new ArrayList<String>(); 
    listofstrings.add("foo"); 
    listofstrings.add("bar"); 
    test.setListOfColors(listofstrings); 

    String xmlRepresentaion = genXML(test); 
    assertTrue(xmlRepresentaion != null); 
    assertTrue(xmlRepresentaion.length() > 0); 
} 

private String genXML(Object object) throws Exception{ 
StringWriter writer = new StringWriter(); 
try { 
      /* I tried the following, but it also throw an NPE 
      JAXBContext jc = JAXBContext.newInstance(TestCollections.class, MapType.class, MapTypeEntry.class); 
      */ 
    JAXBContext jc = JAXBContext.newInstance(TestCollections.class); //<-- NPE 
    Marshaller marshaller = jc.createMarshaller(); 
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
    marshaller.marshal(object, writer); 
}catch (Exception e){ 
    System.out.println("Error marshalling: " + e.getMessage()); 
    e.printStackTrace(System.out); 
    throw e; 
} 
System.out.println(writer.toString()); 
    return writer.toString(); 
} 
+0

私は、JAXBExceptionsがe.getMessage()が提供しない情報をe.toString()が提供する "独自の"形式を持っていることに気付きました。 NPEは他のエラーによってほぼ確実に発生します。誰かが引数なしのコンストラクタやその行に沿った何かを持っていません。 – kylewm

+0

カイルさん、ありがとうございました。この場合、新しい情報は提供していません。 toString()メソッドは、追加のメッセージなしで同じNPEを返します。 – rzrelyea

+0

私は同じ問題を抱えています...マップのオブジェクトタイプが問題のようです。 Map に変更すると問題が解決しました。しかし、String、Number、Dateなどのさまざまな型を透過的にシリアル化したいので、私はまだ解決策を探しています。 – Raman

答えて

0

、あなたはからMapEntryTypeを変更することができます。

@XmlElement 
private String key; 
@XmlElement 
private Object value; 

これは以下のように出力を生成します:

代わりに
<entry> 
    <key>someKey</key> 
    <value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">someValue</value> 
</entry> 

:あなたはMap<String, Object>からMap<String, String>にマップを変更することができればまた

<entry key="someKey">someValue</entry> 

、その後、既存のクラスが動作するはずです。

関連する問題