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