泽西岛(哈希)地图的序列化程序使用?

我正在尝试将以下有效负载发布到基于Jersey的Web服务:

{ "firstname":"Jimmy", "lastname":"Johns", "addresses": [ { "street":"19 Mayberry Drive", "city":"Mayberry", "state":"nc", "postalcode":"27043", "country":"us", "addresstype":1 } ], "data": { "eyes":"blue", "hair":"brown", "sandwich":"roast beef" } } 

我的泽西岛代码:

 @POST public Response create( Person person ) { createBo( person ); <------- stopped here in debugger ... 

就像泽西岛给我打电话一样停下来,我看到的地址正在冲刷出我正在寻找的东西(上面的JSON中有什么)。 但是,我的数据元组不存在。 我知道Jersey正在为Address es调用我的无参数构造函数,并且它的调用者正在被调用,但是我在夜间就像Jersey可能会或可能不会尝试使用这些随机(“数据”)元组一样在我的JSON中。 (我说“随机”,因为在不同的调用中,这些可能是“洞穴”:“深,黑”,“山”:“高,宽”等。这是我界面的一部分。)

为了充实我正在谈论的内容,请将这些POJO视为上述内容:

 @XmlAccessorType( XmlAccessType.FIELD ) @XmlRootElement public class Person implements Serializable { @XmlElement private List
addresses = new ArrayList
(); @XmlElement private Map data = new HashMap(); ... @XmlRootElement public class Address implements Serializable { private String street; private String city; private String state; private String country; private String postalcode; private Integer addresstype; ...

注意:我不能做随机元组,因为我事先并不知道密钥是什么(而我将地址限制为街道城市等)。

我需要的是泽西的HashMap的某种魔术序列化器,我似乎无法很好地理解文档如何编写一个或解决这个问题,同时仍然保持我的界面的灵活性。

我将不胜感激如何实现这一目标。

拉斯贝特曼

PS遗憾地注意到带有Jersey / JAXB / Jackson的Java.util.Map到JSON对象没有帮助,尽管它显示了很大的希望。

注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。

如果您使用MOXy,以下内容将起作用,并且应该与任何其他JAXB提供程序一起使用。 此方法使用XmlAdapterjava.util.Map转换为org.w3c.dom.Element

MapAdapter

XmlAdapter允许您将一个类的实例编组为另一个类的实例(请参阅: 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> { private DocumentBuilder documentBuilder; public MapAdapter() throws Exception { documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } @Override public Element marshal(Map map) throws Exception { Document document = documentBuilder.newDocument(); Element rootElement = document.createElement("data"); document.appendChild(rootElement); for(Entry entry : map.entrySet()) { Element childElement = document.createElement(entry.getKey()); childElement.setTextContent(entry.getValue()); rootElement.appendChild(childElement); } return rootElement; } @Override public Map unmarshal(Element rootElement) throws Exception { NodeList nodeList = rootElement.getChildNodes(); Map map = new HashMap(nodeList.getLength()); for(int x=0; x 

您指定字段/属性应通过@XmlJavaTypeAdapter批注利用@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 

演示

下面是一个独立的示例,您可以运行以certificate一切正常。

 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 properties = new HashMap(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 /输出

 { "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环境中利用MOXyJsonProvider

jackson为您提供设施。 您可以通过将以下内容添加到Application类来强制它。 请注意,这可能会禁用@Path注释类的自动定位。

 @Override public Set getSingletons() { return ImmutableSet . builder() .add(new JacksonJaxbJsonProvider(new ObjectMapper(), JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS)).build(); }