gson is a great library – it works well. Sometimes I have custom requirements, and can make and register TypeAdapters and TypeAdaptorFactories – and that works well too.
What confuses me however, is how to delegate back into json serialization… Most of the time I need this for collections, but to illustrate the point – suppose I had a pair class, which gson would obviously serialize happily, but for some reason I needed my own custom serializer. Well… if my pair is
public class Pair
{
public final Object First;
public final Object Second;
public Pair( Object first, Object second) {this.first = first; this.second = second};
}
If I wrote a type adapter for this – you would want the write function to look like:
public void write( JsonWriter out, Pair pair )
{
out.beginObject();
out.name( "first");
out.value( pair.first ); // can't do this
out.name( "second");
out.value( pair.second); // or this
out.endObject();
}
So you can see the problem – I have no idea the type of first and second, nor how they are serialized. I can use gson.toJson to serialize first and second – but if I add them as a string to the writer, they will be escaped. There is a gson.tojson function that takes a value and a writer – but it also takes a typetoken – which I don't have. I sort of get the impression I'm meant to have another type adapter from somewhere – but when I just have a list of objects… where do I get that? do I just get the adapter for object?
I'm a little confused? Surely this is the most common use case? Most custom serializers will be for a strange list of T or tree of T or something, and you really don't know what is in the list, beyond that it inherits from T… so you need to be able to delegate back the serialization in some way?
Anyway – if someone can tell me how to write the above function, I'd really appreciate it!
Best Answer
In this case its better to use a
JsonSerializer
as opposed to aTypeAdapter
, for the simple reason that serializers have access to their serialization context:The above sample code illustrates how to delegate serialization of target objects back to the main marshaller. The main advantage of this (apart from avoiding complicated workarounds) is that you can still take advantage of other type adaptors and custom serializers that might have been registered in the main context. Note that registration of serializers and adapters use the exact same code:
If you find that you need to stick with an adapter, then you can use an embedded Gson proxy to serialize the Pair properties for you, with the disadvantage that you lose access to custom registrations that you made on the parent Gson proxy: