ObjectHunter
Hunting and gathering in the JEE landscape

I am Frank, a freelance Java developer specialized in backend development from south western germany.

Serializing Apache Jena's RDF resources via JAXB into JSON docments in a JAX-RS context.

posted by fas on 2012-02-17 . Tagged as json, jersey, rdf, java

From a technical point of view at the heart of the semantic web there is RDF. RDF is short for Resource Description Framework, which enables you to annotate any resource in the world wide web identified by an URI with meaningful metadata in a machine readable way. Such an Annotation consists of e.g. the following triple:

"http://congrace.de/tinybo/blog" "http://congrace.de/predicate/#isMaintainedBy" "fas"

with the first part being the subject the second part being the predicate and the third part being the object of a logical statement.
It is important to note that the object can also be the subject of another RDF triple if it's identified by a URI as in the following two triples:

"http://congrace.de/tinybo/blog/articles/86" "http://congrace.de/predicate/#isDerivedFrom" "http://congrace.de/tinybo/blog/articles/65"

"http://congrace.de/tinybo/blog/articles/65" "http://congrace.de/predicate/#isMaintainedBy" "fas"

These relations can be modeled in the Apache Jena framework in the following way:

Model model=ModelFactory.createDefaultModel();
Resource original=model.createResource("http://congrace.de/tinybo/blog");
original.addProperty(model.createProperty("http://congrace.de/predicate/#isMaintainedBy"), fas");


In order to serialize the Jena model to JSON one can use the RDFJenaJsonWriter:

JenaWriterRdfJson writer = new JenaWriterRdfJson();
ByteArrayOutputStream os = new ByteArrayOutputStream();
writer.write(resource.getModel(), os, "RDF/JSON");
System.out.println("os.toString());     


But this doesn't help if the RDF model/resources are part of another Java class and you want to use JAX-RS' possibility to marshal those objects on the fly using e.g. Jersey. However it can be achieved by extending JsonSerializer from the Jackson library:

public class RDFJSONSerializer extends JsonSerializer<Resource> {
    @Override
    public void serialize(Resource resource, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        JenaWriterRdfJson writer = new JenaWriterRdfJson();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        writer.write(resource.getModel(), os, "RDF/JSON");
        jgen.writeRawValue(os.toString().replaceAll("\\n","").replaceAll("\\s+", " "));
    }
}


now it's possible to annotate the Java classes using the Jena model with @JsonSerialize(using = RDFJSONSerializer.class) or@JsonSerialize(contentUsing = RDFJSONSerializer.class) if the Jena classes are part of a Collection:

@XmlElement(name = "relations")
@JsonSerialize(using = RDFJSONSerializer.class)
protected Resource rdf; // RDF relations


in the same manner one can implement a JsonDeserializer to take care of the deserialization of the Jena RDF model.

With this work done it's possible to have it employed by e.g. Jersey to have automagic RDF serialization in your Resources and/or the Jersey client:

ClientResponse result = client.resource(uriPrefix + "/srw/search")
       .accept(MediaType.TEXT_XML)
       .get(ClientResponse.class);
Resource rdf=result.getEntity(Resource.class);


Have fun playing with RDF yourself!



Tags: json, jersey, rdf, java