Jersey Jackson unmarshall JSON

Jersey Jackson unmarshall JSON,json,jersey,jackson,jax-rs,Json,Jersey,Jackson,Jax Rs,我正在开发一个嵌入式jersey实例,它将运行JAXB RESTful服务。我已通过两个步骤配置Jackson: 将此添加到我的POM中 <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.23.2</ver

我正在开发一个嵌入式jersey实例,它将运行JAXB RESTful服务。我已通过两个步骤配置Jackson:

  • 将此添加到我的POM中

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.23.2</version>
    </dependency>
    
    }

  • 我有一个复杂的对象来回传递,如下所示:

    package com.ziath.handheldserver.valueobjects;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.bind.annotation.*;
    
    @SuppressWarnings("restriction")
    @XmlRootElement
    public class Widget {
    
    private String key;
    private String name;
    private List<String> options = new ArrayList<String>();
    private String value;
    private String type;
    
    public Widget(){
        super();
    }
    
    public Widget(String key, String name, List<String> options, String value,
            String type) {
        super();
        this.key = key;
        this.name = name;
        this.options = options;
        this.value = value;
        this.type = type;
    }
    
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<String> getOptions() {
        return options;
    }
    public void setOptions(List<String> options) {
        this.options = options;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    
    @Override
    @GET
    @Path("getKeys")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Widget> getKeys(@QueryParam(value = "page") int page) 
    
    @Override
    @PUT
    @Path("validateKeys")
    @Produces({MediaType.APPLICATION_JSON})
    @Consumes(MediaType.APPLICATION_JSON)
    public boolean validateKeys(@QueryParam(value = "page")int page, @QueryParam(value = "widgets")List<Widget> widgets) 
    
    因此,在我看来,Jackson正确地将我的POJO编组为JSON,但试图将其分解为XML。请注意,我从MOXy转到Jackson,因为我需要能够处理来回的收藏,而MOXy显然无法做到这一点


    我是否错过了告诉Jackson/Jersey双向使用JSON的设置?

    尝试删除
    @QueryParam(value=“widgets”)
    ,因为您应该将其作为实体体传递,而不是查询参数

    @PUT
    @Path("validateKeys")
    @Produces({MediaType.APPLICATION_JSON})
    @Consumes(MediaType.APPLICATION_JSON)
    public boolean validateKeys(@QueryParam(value = "page")int page, List<Widget> widgets) 
    
    我建议阅读一些关于REST设计的讨论,因为您在路径中使用动词:


    我在QueryParam和FormParam之间切换,试图让其中一个正常工作。如果我使用FormParam,我还需要将consumes更改为APPLICATION\u FORM\u URLENCODED


    实际的问题是,Jackson的默认解组是使用XML,因为它被标记为XML资源——去掉它!我最终通过使用一个静态fromString方法解决了如何从JSON中解包的问题。然后处理清单;我不能使用包装器类,因为这需要高度跨语言,并且公开带有列表的包装器会使Python、C#等的实现变得复杂。让它接受带有包装器的列表的方法是多次发布参数(在本例中是小部件)的名称。然后,传入的每个JSON都将针对fromString方法进行调用。

    感谢我在上面给出了答案,并感谢其余语法;我首先自动生成了代码存根,稍后在部署时会清理这些代码存根。您是如何执行PUT的?来自javascript、命令行、JAX-RS客户机或其他什么;我发现问题的答案是Jackson/Jersey会自动将POJO封送到JSON中,但不会将其解组,因此我需要删除顶部与XML相关的注释,并手动放入fromString方法以将JSON解组到对象中。Jersey当然也可以从主体中解组实体。我怀疑您在发出请求时没有提供正确的内容类型头(application/json),这就是为什么我想知道您是如何调用它的(当我从命令行
    curl
    时,我经常忘记
    -H'内容类型:application/json
    ).您好-没有问题是我需要为对象提供一个解组方法-请参阅我自己的答案。提供了正确的内容类型,但在没有帮助器方法的情况下,它无法自动解组JSON-Jersey/Jackson正在寻找来自String的帮助器方法,并且一切正常。现在我提供了解组方法,它工作得很好。不过,感谢您花时间发表评论。我想,如果没有静态fromString方法和@FormParam,您也可以这样做。但听起来你的解决方案适合你!
    Caused by: org.glassfish.jersey.internal.inject.ExtractorException: Error un-marshalling JAXB object of type: class com.ziath.handheldserver.valueobjects.Widget.
        at org.glassfish.jersey.jaxb.internal.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:195)
        at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.convert(AbstractParamValueExtractor.java:139)
        at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.fromString(AbstractParamValueExtractor.java:130)
        at org.glassfish.jersey.server.internal.inject.CollectionExtractor.extract(CollectionExtractor.java:88)
        at org.glassfish.jersey.server.internal.inject.CollectionExtractor$ListValueOf.extract(CollectionExtractor.java:107)
        at org.glassfish.jersey.server.internal.inject.QueryParamValueFactoryProvider$QueryParamValueFactory.provide(QueryParamValueFactoryProvider.java:89)
        ... 38 more
    Caused by: javax.xml.bind.UnmarshalException
     - with linked exception:
    [org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.]
        at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
        at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140)
        at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123)
        at org.glassfish.jersey.jaxb.internal.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:190)
        ... 43 more
    
    @PUT
    @Path("validateKeys")
    @Produces({MediaType.APPLICATION_JSON})
    @Consumes(MediaType.APPLICATION_JSON)
    public boolean validateKeys(@QueryParam(value = "page")int page, List<Widget> widgets) 
    
    @XmlRootElement
    public class Widgets {
    
        private List<Widget> widgets; 
    
        // other fields, setters and getters
    }
    
    @PUT
    @Path("validateKeys")
    @Produces({MediaType.APPLICATION_JSON})
    @Consumes(MediaType.APPLICATION_JSON)
    public boolean validateKeys(@QueryParam(value = "page")int page, Widgets widgets)