deamon
deamon

Reputation: 92580

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 JSON 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?

Upvotes: 29

Views: 53583

Answers (6)

Yaroslav
Yaroslav

Reputation: 466

Maybe you could use http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/beans/BeanUtils.html

BeanUtils.copyProperties(source, target)

Upvotes: 0

joelittlejohn
joelittlejohn

Reputation: 11832

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.

Upvotes: 0

lili
lili

Reputation: 1906

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

Upvotes: 4

StaxMan
StaxMan

Reputation: 116630

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.

Upvotes: 11

Mike K
Mike K

Reputation: 81

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 :-)

Upvotes: 8

Jason Day
Jason Day

Reputation: 8839

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();
    ...
}

Upvotes: 17

Related Questions