如何将JSON对象发布到JAX-RS服务


73

我正在使用JAX-RS的Jersey实现。我想将JSON对象发布到该服务,但收到错误代码415不支持的媒体类型。我想念什么?

这是我的代码:

@Path("/orders")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class OrderResource {

    private static Map<Integer, Order> orders = new HashMap<Integer, Order>();

    @POST
    public void createOrder(Order order) {

        orders.put(order.id, order);
    }

    @GET
    @Path("/{id}")
    public Order getOrder(@PathParam("id") int id) {
        Order order = orders.get(id);
        if (order == null) {
            order = new Order(0, "Buy", "Unknown", 0);
        }
        return order;
    }
}

这是Order对象:

public class Order {
    public int id;
    public String side;
    public String symbol;
    public int quantity;
    ...
}

这样的GET请求可以完美地工作,并以JSON格式返回订单:

GET http://localhost:8080/jaxrs-oms/rest/orders/123 HTTP/1.1

但是,像这样的POST请求返回415:

POST http://localhost:8080/jaxrs-oms/rest/orders HTTP/1.1

{
    "id": "123",
    "symbol": "AAPL",
    "side": "Buy",
    "quantity": "1000"
}

Answers:


82

答案非常简单。我必须Content-TypePOST请求中添加标头,其值为application/json。没有此标头,Jersey不知道如何处理请求正文(尽管有@Consumes(MediaType.APPLICATION_JSON)注释)!


13
Consumes批注仅指示服务器端方法可接受的方法(因此,它的作用是进一步过滤掉HTTP标头中没有Content-Type:application / json的请求)。无论方法使用哪种消耗,您的请求都需要具有Content-Type的原因是因为您使用的JSON库的MessageBodyReader可能仅尝试反序列化请求正文(如果它具有Content-Type:application / json(因为MessageBodyReader可能带有@Consumes(MediaType.APPLICATION_JSON)
布莱恩·卢克

4
如果有人使用apache的HttpClient,请按照以下步骤设置json字符串:postMethod.setRequestEntity(new StringRequestEntity(jsonString,“ application / json”,null));
凯尔2012年

我忘了在POJO(您的情况下为Order类)的顶部添加@XmlRootElement批注
OneWorld 2012年

我遇到了与您完全相同的问题,并且Content-Type:application / json还不够。我还必须在Spring Beans xml中配置一个JsonProvider:<bean id =“ jsonProvider” class =“ org.apache.cxf.jaxrs.provider.json.JSONProvider”> <属性名称=“ singleJaxbContext” value =“ true” /> <属性名= “extraClass”> <列表> <值> package.to.class.Order </值> </列表> </属性> </豆>
杰罗姆Pieret

就我而言,我必须进行以下更改:<br/>post.setEntity(new StringEntity(projdetailpojo.toString())); post.setHeader("Content-Type", "application/json"); HttpResponse response = client.execute(post);
Chandru 2014年

13

Jersey使此过程非常容易,我的服务类与JSON配合良好,我要做的就是在pom.xml中添加依赖项

@Path("/customer")
public class CustomerService {

    private static Map<Integer, Customer> customers = new HashMap<Integer, Customer>();

    @POST
    @Path("save")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public SaveResult save(Customer c) {

        customers.put(c.getId(), c);

        SaveResult sr = new SaveResult();
        sr.sucess = true;
        return sr;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{id}")
    public Customer getCustomer(@PathParam("id") int id) {
        Customer c = customers.get(id);
        if (c == null) {
            c = new Customer();
            c.setId(id * 3);
            c.setName("unknow " + id);
        }
        return c;
    }
}

并在pom.xml中

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.7</version>
</dependency>

9

415通过对我的JAX-rs服务通过PUT / PUSH请求发送序列化为JSON的对象时,我遇到了相同的http错误,换句话说,我的服务器无法从JSON解序列化对象。以我为例,当将相同的对象发送到响应中时,服务器能够成功序列化JSON中的相同对象。

如其他响应中所述,我已将AcceptContent-Type标头正确设置为application/json,但还不够。

我只是忘记了一个默认构造函数,该构造函数没有DTO对象的任何参数。是的,这与@Entity对象背后的原因相同,您需要一个没有参数的构造函数,以便ORM实例化对象并稍后填充字段。

向我的DTO对象添加不带参数的构造函数解决了我的问题。下面是一个类似于我的代码的示例:

错误

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NumberDTO {
    public NumberDTO(Number number) {
        this.number = number;
    }

    private Number number;

    public Number getNumber() {
        return number;
    }

    public void setNumber(Number string) {
        this.number = string;
    }
}

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

    public NumberDTO() {
    }

    public NumberDTO(Number number) {
        this.number = number;
    }

    private Number number;

    public Number getNumber() {
        return number;
    }

    public void setNumber(Number string) {
        this.number = string;
    }
}

我浪费了几个小时,希望这可以节省您的时间;-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.