注: 私はEclipseLink JAXB(MOXy)のリーダーであり、JAXB(JSR-222)エキスパートグループのメンバーです。
以下は、MOXyを使用している場合に機能し、他のJAXBプロバイダーと連携する必要があります。java.util.Map
このアプローチは、org.w3c.dom.Element
を使用してに変換しXmlAdapter
ます。
MapAdapter
AnXmlAdapter
を使用すると、あるクラスのインスタンスを別のクラスのインスタンスとしてマーシャリングできます(http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.htmlを参照)。
package forum11353790;
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class MapAdapter extends XmlAdapter<Element, Map<String, String>> {
private DocumentBuilder documentBuilder;
public MapAdapter() throws Exception {
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
@Override
public Element marshal(Map<String, String> map) throws Exception {
Document document = documentBuilder.newDocument();
Element rootElement = document.createElement("data");
document.appendChild(rootElement);
for(Entry<String,String> entry : map.entrySet()) {
Element childElement = document.createElement(entry.getKey());
childElement.setTextContent(entry.getValue());
rootElement.appendChild(childElement);
}
return rootElement;
}
@Override
public Map<String, String> unmarshal(Element rootElement) throws Exception {
NodeList nodeList = rootElement.getChildNodes();
Map<String,String> map = new HashMap<String, String>(nodeList.getLength());
for(int x=0; x<nodeList.getLength(); x++) {
Node node = nodeList.item(x);
if(node.getNodeType() == Node.ELEMENT_NODE) {
map.put(node.getNodeName(), node.getTextContent());
}
}
return map;
}
}
人
フィールド/プロパティがアノテーションXmlAdapter
を介してを活用する必要があることを指定します。@XmlJavaTypeAdapter
package forum11353790;
import java.io.Serializable;
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType( XmlAccessType.FIELD )
@XmlRootElement
public class Person implements Serializable {
private String firstname;
private String lastname;
private List< Address > addresses = new ArrayList< Address >();
@XmlAnyElement
@XmlJavaTypeAdapter(MapAdapter.class)
private Map< String, String > data = new HashMap< String, String >();
}
住所
package forum11353790;
import java.io.Serializable;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Address implements Serializable {
private String street;
private String city;
private String state;
private String country;
private String postalcode;
private Integer addresstype;
}
jaxb.properties
MOXyをJAXBプロバイダーとして指定するには、jaxb.properties
ドメインモデルと同じパッケージで呼び出されるファイルに次のエントリを含める必要があります(http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-asを参照)。 -your.html)。
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
デモ
以下は、すべてが機能することを証明するために実行できるスタンドアロンの例です。
package forum11353790;
import java.io.FileInputStream;
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>(2);
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {Person.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource json = new StreamSource(new FileInputStream("src/forum11353790/input.json"));
Person person = unmarshaller.unmarshal(json, Person.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(person, System.out);
}
}
input.json / Output
{
"firstname" : "Jimmy",
"lastname" : "Johns",
"addresses" : [ {
"street" : "19 Mayberry Drive",
"city" : "Mayberry",
"state" : "nc",
"country" : "us",
"postalcode" : "27043",
"addresstype" : 1
} ],
"data" : {
"sandwich" : "roast beef",
"hair" : "brown",
"eyes" : "blue"
}
}
MOXyおよびJAX-RS/Jersey
MOXyJsonProvider
クラスを活用することにより、JAX-RS環境でMOXyを活用できます。