You can use the Variant
mechanisms of JAX-RS.
@GET
@Path("/locations/{id}")
@Produces(value = {"application/vnd.mycompany-v2+json", // current version
"application/vnd.mycompany-v1+json", // old version
MediaType.APPLICATION_JSON}) // fallback
public Response getLocation(@PathParam("id") Integer id,
@Context Request request) {
MediaType vndTypeV1 = new MediaType("application", "vnd.mycompany-v1+json");
MediaType vndTypeV2 = new MediaType("application", "vnd.mycompany-v2+json");
Variant variant1 = new Variant(vndTypeV1, null, null);
Variant variant2 = new Variant(vndTypeV2, null, null);
Variant variantJson = new Variant(MediaType.APPLICATION_JSON_TYPE, null, null);
List<Variant> variants = new ArrayList<Variant>();
variants.add(variant1);
variants.add(variant2);
variants.add(variantJson);
Variant selectedVariant = request.selectVariant(variants);
Location location = someBackendService.getLocation(id);
// Manipulate location according to which variant is the selectedVariant.
// ...
return Response.ok("{}")
.header(HttpHeaders.CONTENT_TYPE, selectedVariant.getMediaType())
.build();
}
See the Java EE 6 Tutorial, too.
Edit
There is no automatic way to marshal an entity according to the selected variant. This requires some manual work. For example:
String version = extractVersionFromVariant(selectedVariant);
if ("v1".equals(version)) {
location.setSomeV1Propery("only in v1);
} else if ("v2".equals(version)) {
location.setSomeV2Propery("only in v2);
}
return Response.ok(location)
.header(HttpHeaders.CONTENT_TYPE, selectVariant.getMediaType())
.build();
If the versions are different enough, I'd use a JAXB annotated class for each version. Each such class would then only contain those properties that are valid for this version. JAX-RS takes care to marshal them to JSON.