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

Nar*_*esh 66 json jax-rs jersey

我正在使用JAX-RS的Jersey实现.我想POST一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Order对象:

public class Order {
    public int id;
    public String side;
    public String symbol;
    public int quantity;
    ...
}
Run Code Online (Sandbox Code Playgroud)

像这样的GET请求可以很好地工作并以JSON格式返回一个订单:

GET http://localhost:8080/jaxrs-oms/rest/orders/123 HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

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

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

{
    "id": "123",
    "symbol": "AAPL",
    "side": "Buy",
    "quantity": "1000"
}
Run Code Online (Sandbox Code Playgroud)

Nar*_*esh 78

答案非常简单.我不得不Content-TypePOST请求中添加一个标头值为application/json.没有这个标题,泽西岛不知道如何处理请求体(尽管有@Consumes(MediaType.APPLICATION_JSON)注释)!

  • Consumes注释仅指示服务器端方法可接受的内容(因此它的作用是进一步过滤掉HTTP头中没有Content-Type:application/json的请求).您的请求需要具有Content-Type而不管方法上的Consumes的原因是因为您使用的JSON库的MessageBodyReader可能仅尝试反序列化请求主体(如果它具有Content-Type:application/json(因为MessageBodyReader可能有一个@Consumes(MediaType.APPLICATION_JSON就可以了). (13认同)
  • 如果有人使用apache的HttpClient,这里是你如何设置json字符串:postMethod.setRequestEntity(new StringRequestEntity(jsonString,"application/json",null)); (4认同)

glm*_*glm 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在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>
Run Code Online (Sandbox Code Playgroud)


Fab*_*lao 6

415发送对象,序列化为JSON,通过PUT/PUSH请求到我的JAX-rs服务时遇到了相同的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我失去了几个小时,我希望这会拯救你的;-)