I have a class

class Foo {
   int id;
   String name;
}

Using the JsonHierarchicalStreamDriver I can turn this into JSON:

{"id":1, "name":"x"}

I want to auto-create a secondary node which is link to the Resource in a REST interface, ie.:

{"id":1, "link":"http://host/path/foo/1";, "name":"x"}

I have managed to achieve this using a simple converter:

public class IdAndLinkConverter implements Converter {

    private final UriBuilder baseUriBuilder;
    private final String path;

    public IdAndLinkConverter(UriBuilder baseUriBuilder, String path) {
        this.baseUriBuilder = baseUriBuilder;
        this.path = path;
    }

    public boolean canConvert(Class type) {
        return Number.class.isAssignableFrom(type);
    }

public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        Number id = (Number) source;
        writer.setValue(id.toString());

        writer.endNode();
        writer.startNode("link");
        URI uri = baseUriBuilder.path(path).build(id);
        writer.setValue(uri.toString());
    }

public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        throw new NotImplementedException();
    }
}

And I configure this to be associated to a specific field like this:

xstream.registerLocalConverter(Foo.class, "id", new IdAndLinkConverter(baseUriBuilder, "/foo"));

(The javax.ws.rs.core.UriBuilder argument handles creation of the link.)

The "cheat" is the writer.endNode(), writer.startNode(..) which allows me to inject a second node whilst I serialize the first field.

Job done.  Until I now want to build a more complex REST url, e.g.:

class Baa {
   int id;
   int fooId;
   String name;
}

{"id":7, "fooId":1, "link":"http://host/path/foo/1/bar/7";, "name":"y"}

Now my link field requires two source fields to make it. The converter approach above does not allow access to the parent object so I am stuck.

OK, so I could write my own Converter for the Baa class; that's easy enough, but not as elegant and long-term robust as the IdAndLinkConverter. Writing my own Converter requires this custom Converter to be maintained as the Bar class is changed - i.e. adding new fields.

I was thinking that I might be able to subclass the ReflectionConverter which I believe handles all general classes. I can see marshallField(..) but this does not provide access to the original object which I need to be able to get to both by id fields.

Another idea I had was to subclass ReflectionConverter and watch every field go by and save the ones I am interesting in the MashallingContext's put/get data holder. Then when the second field I want comes along I am good to go. But I am not clear on the life cycle of the MashallingContext and whether this is an appropriate usage of the data holder.

No doubt someone has thought of this before. What's the best way to approach my requirement, please?

By the way, I only need to handle serialization or marhsalling, not unmarhsalling.

Andrew.


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email


Reply via email to