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
Put a key/value pair in the JSONObject, where the value will be a JSONArray which is produced from a Collection. But it puts JSON representation of your object as String. So you should use either JSONArrays or Java objects. You should not mix them.
JSON defines only two data structures: objects and arrays. An object is a set of name-value pairs, and an array is a list of values. JSON defines seven value types: string, number, object, array, true, false, and null.
Jersey endpoints and return a JSON responseCreate a few endpoints in Jersey, and Jackson will handle the object from/to JSON conversion. 4.1 Create the following endpoints and return JSON response. GET /json/ , returns a JSON string. GET /json/{name} , returns an User object containg the {name} in JSON string.
Jersey uses Jackson internally to convert Java objects to JSON and vice versa.
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.
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}, ...]
}
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With