Skip to content

JsonSerializable interface to mark classes as serializable #2788

@AnAwesomGuy

Description

@AnAwesomGuy

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions