可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am building a RESTful web-service in Java using Jersey 1.11, and have problems implementing a method which consumes a list of JSON-ised entities. The single instance method works fine.
The error I get is:
Status 400 - Bad Request. The request sent by the client was syntactically incorrect.
My method signature looks like this:
@POST
@Path("/some-path/{someParam}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String createBatch(List<MyEntity> myEnts, @PathParam("someParam") String someParam)
{
...
}
The JSON I am sending in the requests is an array of MyEntity
JSON objects:
[{"field1" : value1, "field2" : value2}, {"field1" : value3, "field2" : value4}, ...]
Similar questions have been asked before and one straight forward suggestion was to change the consumed media type to text and de-serialize the JSON manually but I'd prefer a cleaner solution.
Is the JSON I am sending even valid in this context or do I need a top-level {}
i.e a wrapper entity? This would also seem a bit un-natural.
Thank you,
/David
回答1:
I think PathParam and also a Param which should unmarshalled by Jersey(JAX-RS) is not possible.
Please try to remove the PathParam Parameter.
And if you need the second Parameter so create a new class like this
@XmlRootElement(name = "example")
public class Example {
@XmlElement(name = "param")
private String param;
@XmlElement(name = "entities")
private List<MyEntity> entities;
}
and also modify your Methode :
@POST
@Path("/some-path")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String createBatch(Example example)
{
...
}
your JSON Should look like this:
{
"param":"someParam",
"entities":[
{"field1" : value1, "field2" : value2}, {"field1" : value3, "field2" : value4}, ...]
}
回答2:
Ok, so in the end I solved this using a simple wrapper class in order to generate { items : [{ <myEnityInstanceJson1> }, { <myEnityInstanceJson2> }, ... ]}
. I guess there is a way to have a generic wrapper but for now this will do:
@XmlRootElement
public class MyEntityWrapper implements Serializable {
private static final long serialVersionUID = 1L;
private List<MyEntity> items;
public MyEntityWrapper() {
this.items = new ArrayList<MyEntity>();
}
public MyEntityWrapper(List<MyEntity> items) {
this.items = items;
}
public List<MyEntity> getItems() {
return items;
}
public void setItems(List<MyEntity> items) {
this.items = items;
}
}
回答3:
The problem is the generic list type, which is not available at runtime due to type erasure, so Jersey wont know what kind of POJOs to unmarshal.
I think the simplest solution (which I know works, at least when using Jackson in your MessageBodyReader
) in this case would be to just use a normal Java array instead of the List, so the method signature becomes:
public String createBatch(@PathParam("someParam") String someParam, MyEntity[] myEnts)
And yes, combining @PathParam
and a consumed/unmarshalled body parameter should be fine.
回答4:
Wrapper class works.
MyEntity[] myEnts
doesn't work.
This is what I did and it worked.
public String createBatch(@PathParam("someParam") String someParam,
String content)
Use ObjectMapper
to convert to List of objects.
List<MyEntity> entities = om.readValue(content,
new TypeReference<List<MyEntity>>(){}).
回答5:
This is valid JSON for an array:
{"elements": [
{"field1" : value1, "field2" : value2},
{"field1" : value3, "field2" : value4},
...]
};
(see here for an example)
You don't need to send text, you can send it as JSON. Also your MyEntity
should have @XmlRootElement
on it (see here, section 5.2 for an example).
You don't need PathParam
in your arguments, someParam
is available when the request is posted if you leave the @Path("/some-path/{someParam}")
in your method signature .