Convert JSON query parameters to objects with JAX-RS
I have a JAX-RS resource, which gets its paramaters as a JSON string like this:
http://some.test/aresource?query={"paramA":"value1", "paramB":"value2"}
The reason to use JS开发者_如何学CON here, is that the query object can be quite complex in real use cases.
I'd like to convert the JSON string to a Java object, dto in the example:
@GET
@Produces("text/plain")
public String getIt(@QueryParam("query") DataTransferObject dto ) {
...
}
Does JAX-RS support such a conversion from JSON passed as a query param to Java objects?
Yes, you can do this, but you will need to write the conversion code yourself. Fortunately, this is easy, you just need to write a class that has a public String
constructor to do the conversion. For example:
public class JSONParam {
private DataTransferObject dto;
public JSONParam(String json) throws WebApplicationException {
try {
// convert json string DataTransferObject and set dto
}
catch (JSONException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
.entity("Couldn't parse JSON string: " + e.getMessage())
.build());
}
}
public DataTransferObject getDTO() {
return dto;
}
}
Then you can use:
@GET
@Produces("text/plain")
public String getIt(@QueryParam("query") JSONParam json) {
DataTransferObject dto = json.getDTO();
...
}
As mentioned, you do need to explicitly convert from String parameter to JSON. But there is no need to use something as primitive as org.json's parser; Jackson or Gson can do data binding (String to JSON, JSON to POJO) in a line or two. With Jackson:
MyValue value = new ObjectMapper().readValue(json, MyValue.class);
(for production code, just create ObjectMapper once as static member, reuse)
Jackson is what most JAX-RS implementations use to implement data-binding for POST data, so this is quite similar.
Adding to Jason's solution, using http://www.json.org/java/ (courtesy of Crockford):
import org.json.JSONObject;
public class JSONParam {
private DataTransferObject dto;
public JSONParam(String json) throws WebApplicationException {
try {
// convert json string DataTransferObject and set dto
JSONObject jo = new JSONObject(json);
dto.setParamA(jo.getString("paramA"));
dto.setParamB(jo.getString("paramB"));
// There are other get methods for Integer, Double, etc.
// You can also build JSON from Java objects.
}
catch (JSONException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
.entity("Couldn't parse JSON string: " + e.getMessage())
.build());
}
}
public DataTransferObject getDTO() {
return dto;
}
}
Don't re-invent the wheel :-)
JAX-RS supports the use of JAXB (Java API for XML Binding) to bind a JavaBean to XML or JSON and vise versa. More details can be found here, for example: http://www.ibm.com/developerworks/web/library/wa-aj-tomcat/index.html
You need to
- Add @XmlRootElement annotation on DataTransferObject
- Create it an empty default constructor in DataTransferObject
- Add @Consumes(MediaType.APPLICATION_JSON) annotation to your WebService
If you're interested in generating your DTOs, can I suggest jsonschema2pojo? You can define your objects using JSON Schema and have your DTOs automatically generated.
Once you've written the schema, you can also give it to your consumers so that they understand exactly how requests should be formatted.
Maybe you could use http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/beans/BeanUtils.html
BeanUtils.copyProperties(source, target)
精彩评论