Repository navigation
JsonSerializable interface to mark classes as serializable #2788
Copy link
Copy link
Open
Labels
Description
Problem solved by the feature
Allow classes to be marked as serializable without needing another class as the serializer.
Is this similar to #594?
Feature description
It would work similarly to Java's Comparable interface, so you wouldn't need a serializer in another class.
Currently, you need to either add a TypeAdapter as an external class through @JsonAdapter or GsonBuilder, but it would be much more convenient if the instance (of the object we're serializing) could serialize itself.
The implementation could look a little something like this (not the best code, triple nested anonymous classes my beloved) (I code in 4 spaces so the formatting may be a bit wonk):
public interface JsonSerializable {
TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
return !JsonSerializable.class.isAssignableFrom(type.getRawType()) ?
null : // return early if it isn't JsonSerializable
new TypeAdapter<>() { // SerializationDelegatingTypeAdapter? not sure what it does
private TypeAdapter<T> delegate;
private JsonSerializationContext context;
@Override
public void write(JsonWriter out, T value) throws IOException {
if (value instanceof JsonSerializable) // implicit null check
Streams.write(((JsonSerializable)value).serialize(type.getType(), context()), out);
else
delegate().write(out, value);
}
@Override
public T read(JsonReader in) throws IOException {
return delegate().read(in);
}
private TypeAdapter<T> delegate() { // taken from Excluder
TypeAdapter<T> d = delegate;
return d != null
? d
: (delegate = gson.getDelegateAdapter(JsonSerializable.FACTORY, type));
}
private JsonSerializationContext context() {
JsonSerializationContext jsc = this.context;
return jsc != null
? jsc
: (context = new JsonSerializationContext() { // expose GsonContextImpl?
@Override
public JsonElement serialize(Object src) {
return gson.toJsonTree(src);
}
@Override
public JsonElement serialize(Object src, Type typeOfSrc) {
return gson.toJsonTree(src, typeOfSrc);
}
});
}
};
}
};
JsonElement serialize(Type thisType, JsonSerializationContext context);
}Alternatives / workarounds
Implement the serializer or TypeAdapter in another class.
Reactions are currently unavailable
Activity
Marcono1234 commentedon Jan 13, 2025
To me it sounds as if this is the same feature request. The only difference might be that the other feature request also requests this for deserialization.
Note that the adapter class can be a nested static class (so that it can access private fields of the enclosing class), but when referencing it in
@JsonAdapteryou might have to qualify its name with the name of the enclosing class. For example something like:The following are just some personal thoughts on this:
serializemethod should probably use aJsonWriterparameter though instead ofJsonElementas return type for better performance. And maybe it would also need aGsonparameter to allow looking up other adapters, e.g. to serialize field values.deserializemethod on it. But then it cannot set anyfinalfields.TypeAdapterFactorywhose created type adapters are cached byGson, it seems here there is no way to cache anything for serialization. So theserializemethod would have to look up delegate adapters every time it is called (assuming theserializemethod has aGsonparameter, as mentioned above).This might not cause a big overhead though.
So personally I am not completely sure if that would really provide such a big advantage over using
@JsonAdapteron a class.