当前位置: 首页 > 知识库问答 >
问题:

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

袁建木
2023-03-14

我正在尝试将以下有效负载发布到我基于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
    ...

就在Jersey给我打电话的时候,我停下了,我看到了我正在寻找的地址(上面JSON中的内容)。然而,我的数据元组不在那里。我知道Jersey正在为地址es调用我的无参数构造函数,它的setters也在被调用,但是我还没睡,因为Jersey可能会也可能不会尝试对JSON中的这些随机("数据")元组做些什么。(我说“随机”是因为在不同的调用中,这些可能是“洞穴”:“深、暗”、“山”:“高、宽”等。这是我界面的一部分。)

为了充实我所说的内容,请将这些POJOs视为上述内容的背景:

@XmlAccessorType( XmlAccessType.FIELD )
@XmlRootElement
public class Person implements Serializable
{
    @XmlElement
    private List< Address > addresses = new ArrayList< Address >();

    @XmlElement
    private Map< String, String > data = new HashMap< String, String >();

    ...

@XmlRootElement
public class Address implements Serializable
{
    private String  street;
    private String  city;
    private String  state;
    private String  country;
    private String  postalcode;
    private Integer addresstype;
    ...

注意:我不能像做Address那样做随机元组,因为我实际上事先不知道键是什么(而我将Address限制为street、city等)。

我需要的是泽西岛HashMaps的某种神奇序列化程序,我似乎无法很好地解释文档,无法理解如何编写或解决这个问题,同时仍然保持接口的灵活性。

我将感谢关于如何实现这一目标的任何指示。

拉斯·贝特曼

附言:可悲的是,Java.util.映射到带有泽西岛/ JAXB / 杰克逊的JSON对象并没有帮助,尽管它显示出了很大的希望。

共有2个答案

郎长卿
2023-03-14

Jackson为您提供了该工具。您可以通过将以下内容添加到您的Application类来强制执行它。请注意,这可能会禁用您的@Path注释类的自动位置。

@Override
public Set<Object> getSingletons() {
    return ImmutableSet
            .<Object> builder()
            .add(new JacksonJaxbJsonProvider(new ObjectMapper(),
                    JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS)).build();
}
巴博耘
2023-03-14

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

如果您使用的是 MOXy,则以下内容将起作用,并且应该与任何其他 JAXB 提供程序一起使用。此方法使用 Xml 适配器Java.util.Map 转换为组织.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<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;
    }

}

指定字段/属性应通过@XmlJavaTypeAdapter批注来利用 Xml 适配器

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提供者,您需要在与您的域模型相同的包中包含一个名为< code>jaxb.properties的文件,其中包含以下条目(请参见:http://blog . bdoughan . com/2011/05/specifying-eclipse link-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/输出

{
   "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/泽西岛

您可以通过利用 MOX-RS 提供程序类在 JAX-RS 环境中利用 MOXY

  • http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html
 类似资料:
  • 问题内容: 我正在尝试将以下有效负载发布到基于泽西岛的Web服务中: 我的泽西岛代码: 就在Jersey打电话给我时,我停了下来,我看到 当面的 地址正好与我要查找的内容(上面的JSON中的内容)完全冲了出来。但是,我的数据元组不存在。我知道Jersey正在为 Address es 调用我的no- arg构造函数,并且它的setter也被调用了,但是我晚上仍无法解决Jersey可能会或可能不会尝试

  • 我目前使用的是球衣 我现在要做的是设置泽西,这样当查询参数进来时(比如缩进),我可以告诉Jackson以“更漂亮的格式,也就是缩进”序列化JSON。您可以通过使用SerializationConfig.Feature.INDENT_OUTPUT配置JSON映射器来轻松地告诉Jackson这样做。 问题是,我如何在每个请求的基础上获取一个queryparam并使用它来修改Jackson的输出?

  • 问题内容: 我设置了一个Eclipse WebApp项目,并将Jersey和Jackson JAR放在WEB-INF / lib目录中。我想使用JSON序列化,但无法解决此错误: 在 WEB-INF / lib目录 文件夹包含以下JAR: web.xml : Greeting.java : WebApp项目在嵌入式Tomcat v7服务器中运行(在eclipse中查看“服务器”)。 要求 : 只要

  • 问题内容: 我有一个使用以下实现的基于json的REST Web服务:使用Jackson的Jetty,Jersey,Jersey-JSON。 我的方法之一收到一个Person实例,该实例的字段类型为。即: 如果我使用名称数组来调用它,一切正常!例如: 但是,如果该人只有一个名字,我的客户会创建一个值元素,例如: 当我尝试使用单个值调用服务时,出现异常: 题: 我应该如何创建/配置Web服务,以便在

  • 问题内容: 我有一个Jersey REST API,并且正在使用来处理授权。我还在所有端点上使用,以便我的API可以处理数千个并发请求。 我的授权过滤器命中了一个远程服务,但是当运行过滤器时,Jersey尚未将当前线程添加到它的内部,因此我完全失去了异步的好处。 我可以告诉Jersey我希望这是异步的吗? 这是一个示例资源: 更新 刚刚收到泽西队球员的回音,从2.7开始,这是不可能的。只有资源方法

  • 我很难理解泽西岛的注入机制。JAX-RS规范(http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-520005)指出,在应用程序子类、根资源类和提供程序中可以通过@Context进行注入。 我现在有一个在启动时实例化的类,并且有一个在每次请求时调用的方法。在方法内部,我需要访问当前的UriInfo对象。问题是,这个方法不是从我的