Use with Gson #6

Closed
f2prateek opened this Issue Jun 4, 2014 · 24 comments

Comments

Projects
None yet
8 participants
@f2prateek

Could you annotate your model classes with AutoValue when using with Gson? Since Gson uses fields directly, I wasn't sure how it would work.

@f2prateek

This comment has been minimized.

Show comment
Hide comment
@f2prateek

f2prateek Jun 4, 2014

@AutoValue
abstract class Foo implement Parcelable {
  public static Foo create(int id) {
    return new AutoValue_Foo(id);
  }

  abstract int id();
}

Foo foo = Foo.create(1);
Gson gson = new GsonBuilder().........build();
String json = gson.toJson(foo);
gson.fromJson(json, Foo.class);
@AutoValue
abstract class Foo implement Parcelable {
  public static Foo create(int id) {
    return new AutoValue_Foo(id);
  }

  abstract int id();
}

Foo foo = Foo.create(1);
Gson gson = new GsonBuilder().........build();
String json = gson.toJson(foo);
gson.fromJson(json, Foo.class);
@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Jun 4, 2014

Outgoing serialization will work. Incoming serialization needs pointed at the generated class rather than the model class.

private class FooDeserializer implements JsonDeserializer<Foo> {
  public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
    return context.deserialize(json, AutoParcel_Foo.class);
  }
}

Outgoing serialization will work. Incoming serialization needs pointed at the generated class rather than the model class.

private class FooDeserializer implements JsonDeserializer<Foo> {
  public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
    return context.deserialize(json, AutoParcel_Foo.class);
  }
}
@f2prateek

This comment has been minimized.

Show comment
Hide comment
@f2prateek

f2prateek Jun 4, 2014

I had something similar but is there a way to do it for all model classes rather than registering a JsonDeserializer for each model class?

I had something similar but is there a way to do it for all model classes rather than registering a JsonDeserializer for each model class?

@f2prateek

This comment has been minimized.

Show comment
Hide comment
@f2prateek

f2prateek Jun 4, 2014

What I'm currently doing is look up the class name and prefix AutoValue_ for Gson to know about the generated class.

What I'm currently doing is look up the class name and prefix AutoValue_ for Gson to know about the generated class.

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Jun 4, 2014

No. You could write another annotation processor for @AutoParcel which generated the JsonDeserializer types and then an AutoParcelGsonRegistry which was a visitor for Gson.Builder to register them all.

No. You could write another annotation processor for @AutoParcel which generated the JsonDeserializer types and then an AutoParcelGsonRegistry which was a visitor for Gson.Builder to register them all.

@f2prateek

This comment has been minimized.

Show comment
Hide comment
@f2prateek

f2prateek Jun 4, 2014

A code generator for a code generator? Nice!

A code generator for a code generator? Nice!

@f2prateek f2prateek closed this Jun 4, 2014

@frankiesardo

This comment has been minimized.

Show comment
Hide comment
@frankiesardo

frankiesardo Jun 5, 2014

Owner

This is such a common use case that I guess the library should provide an auto-parcel-gson-processor. Jackson integration works out of the box thanks to @JsonConstructor but it's definitely too verbose and there are large margins of improvements that an auto-parcel-jackson-processor could address.
I'll reopen the issue to have point for discussion and a reference if somebody wants to push some code for it ;)

Owner

frankiesardo commented Jun 5, 2014

This is such a common use case that I guess the library should provide an auto-parcel-gson-processor. Jackson integration works out of the box thanks to @JsonConstructor but it's definitely too verbose and there are large margins of improvements that an auto-parcel-jackson-processor could address.
I'll reopen the issue to have point for discussion and a reference if somebody wants to push some code for it ;)

@frankiesardo frankiesardo reopened this Jun 5, 2014

@hvisser

This comment has been minimized.

Show comment
Hide comment
@felipecsl

This comment has been minimized.

Show comment
Hide comment
@felipecsl

felipecsl Oct 2, 2014

Contributor

Looks like this would be useful here

Contributor

felipecsl commented Oct 2, 2014

Looks like this would be useful here

@lzyzsd

This comment has been minimized.

Show comment
Hide comment
@lzyzsd

lzyzsd Oct 22, 2014

@JakeWharton, your solution works for most situations, but what if I want to use Gson annotations like SerializedName?

lzyzsd commented Oct 22, 2014

@JakeWharton, your solution works for most situations, but what if I want to use Gson annotations like SerializedName?

@f2prateek

This comment has been minimized.

Show comment
Hide comment
@f2prateek

f2prateek Oct 22, 2014

That won't work out of the box, you would have to modify AutoParcel to recognize @SerializedName on the methods and add it to the fields in the generated class.

That won't work out of the box, you would have to modify AutoParcel to recognize @SerializedName on the methods and add it to the fields in the generated class.

@lzyzsd

This comment has been minimized.

Show comment
Hide comment
@lzyzsd

lzyzsd Oct 22, 2014

@f2prateek yes, I am working on this approach now.

lzyzsd commented Oct 22, 2014

@f2prateek yes, I am working on this approach now.

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Oct 22, 2014

That's not a very scalable or generalized solution.
On Oct 22, 2014 9:00 AM, "Bruce Lee" notifications@github.com wrote:

@f2prateek https://github.com/f2prateek yes, I am working on this
approach now.


Reply to this email directly or view it on GitHub
#6 (comment)
.

That's not a very scalable or generalized solution.
On Oct 22, 2014 9:00 AM, "Bruce Lee" notifications@github.com wrote:

@f2prateek https://github.com/f2prateek yes, I am working on this
approach now.


Reply to this email directly or view it on GitHub
#6 (comment)
.

@felipecsl

This comment has been minimized.

Show comment
Hide comment
@felipecsl

felipecsl Oct 22, 2014

Contributor

@JakeWharton what would you recommend instead?

Contributor

felipecsl commented Oct 22, 2014

@JakeWharton what would you recommend instead?

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Oct 22, 2014

I don't know. But you can't special Gson because, well, that's just not a reasonable solution. You can't blindly copy annotations from the methods to fields because the @Target of them might not allow placement on a field (or even placement on the method in the first place). The only other solution I can think of is extremely convoluted and complex for something that's otherwise trivial so I'm not even going to mention it.

Unless this library becomes AutoGsonParcel I don't think this should be done at all.

The fact that AutoParcel generates code to fulfill the immutability and Parcelable contract is an implementation detail. I should be able to swap out AutoParcel for something else without effecting the Gson serialization of these types.

I don't know. But you can't special Gson because, well, that's just not a reasonable solution. You can't blindly copy annotations from the methods to fields because the @Target of them might not allow placement on a field (or even placement on the method in the first place). The only other solution I can think of is extremely convoluted and complex for something that's otherwise trivial so I'm not even going to mention it.

Unless this library becomes AutoGsonParcel I don't think this should be done at all.

The fact that AutoParcel generates code to fulfill the immutability and Parcelable contract is an implementation detail. I should be able to swap out AutoParcel for something else without effecting the Gson serialization of these types.

@frankiesardo

This comment has been minimized.

Show comment
Hide comment
@frankiesardo

frankiesardo Oct 23, 2014

Owner

Personally quite against annotating your model object with anything that has to do with serialisation. The reason being that you complect data and representation of data (Gson, Jackson, Xml, Cursor). I'd like to freely swap between serialisers without re-annotating my model objects.

But the truth is those annotations are pretty convenient, so I'd like to find a lean way to provide the same semantic but with a different strategy. Jake, let's see how this scores as a fairly convoluted solution:

@GsonKeyMapper(GsonFooMapper.class)
@JacksonKeyMapper(JacksonFooMapper.class)
@ContentValueKeyMapper(ContentValueFooMapper.class)
public class Foo {...}

A specific annotation processor could generate the required Gson bindings for the Foo class using the GsonFooMapper. A mapper can use its library-specific dsl, like so:

public abstract class GsonFooMapper extends Foo {
  @SerialisedName("x")
  public abstract String y();
}

That way the serialisation mechanisms are composable and easy to refactor. I wish best of luck to anybody who wants to go down that path, tho.

Owner

frankiesardo commented Oct 23, 2014

Personally quite against annotating your model object with anything that has to do with serialisation. The reason being that you complect data and representation of data (Gson, Jackson, Xml, Cursor). I'd like to freely swap between serialisers without re-annotating my model objects.

But the truth is those annotations are pretty convenient, so I'd like to find a lean way to provide the same semantic but with a different strategy. Jake, let's see how this scores as a fairly convoluted solution:

@GsonKeyMapper(GsonFooMapper.class)
@JacksonKeyMapper(JacksonFooMapper.class)
@ContentValueKeyMapper(ContentValueFooMapper.class)
public class Foo {...}

A specific annotation processor could generate the required Gson bindings for the Foo class using the GsonFooMapper. A mapper can use its library-specific dsl, like so:

public abstract class GsonFooMapper extends Foo {
  @SerialisedName("x")
  public abstract String y();
}

That way the serialisation mechanisms are composable and easy to refactor. I wish best of luck to anybody who wants to go down that path, tho.

@jkwiecien

This comment has been minimized.

Show comment
Hide comment
@jkwiecien

jkwiecien Oct 29, 2014

Gson also need an empty constructor, right? Those are abstract classes :)

Gson also need an empty constructor, right? Those are abstract classes :)

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Oct 29, 2014

Not since version 2, no. And we are talking about deserialization using the
generated implementation class, not the abstract class.
On Oct 29, 2014 8:37 AM, "jkwiecien" notifications@github.com wrote:

Gson also need an empty constructor, right? Those are abstract classes :)


Reply to this email directly or view it on GitHub
#6 (comment)
.

Not since version 2, no. And we are talking about deserialization using the
generated implementation class, not the abstract class.
On Oct 29, 2014 8:37 AM, "jkwiecien" notifications@github.com wrote:

Gson also need an empty constructor, right? Those are abstract classes :)


Reply to this email directly or view it on GitHub
#6 (comment)
.

@frankiesardo

This comment has been minimized.

Show comment
Hide comment
@frankiesardo

frankiesardo Oct 29, 2014

Owner

Gson would not directly construct a GsonFooMapper. An annotation processor will use the GsonFooMapper to generate the right deserializer for Foo

Owner

frankiesardo commented Oct 29, 2014

Gson would not directly construct a GsonFooMapper. An annotation processor will use the GsonFooMapper to generate the right deserializer for Foo

@frankiesardo

This comment has been minimized.

Show comment
Hide comment
@frankiesardo

frankiesardo Oct 29, 2014

Owner

It's even better if the model object is not annotated at all.
It should be safe to generate the Gson deserializers from external spec classes.

@GsonSerializationSpec(Foo.class)
public abstract class FooGsonSpec extends Foo {
  @SerialisedName("x")
  public abstract String y();
}

That way adding a new serialisation option / changing the serialisation logic for your models will leave your model classes untouched.
I hope that's less confusing.

Owner

frankiesardo commented Oct 29, 2014

It's even better if the model object is not annotated at all.
It should be safe to generate the Gson deserializers from external spec classes.

@GsonSerializationSpec(Foo.class)
public abstract class FooGsonSpec extends Foo {
  @SerialisedName("x")
  public abstract String y();
}

That way adding a new serialisation option / changing the serialisation logic for your models will leave your model classes untouched.
I hope that's less confusing.

@dkozel dkozel referenced this issue in johncarl81/parceler Jul 28, 2015

Closed

Location of generated classes? [Android Studio] #118

@johnkil

This comment has been minimized.

Show comment
Hide comment
@johnkil

johnkil Jul 30, 2015

@frankiesardo what about this issue, can we expect in the near future the implementation based on GsonSerializationSpec annotation?

johnkil commented Jul 30, 2015

@frankiesardo what about this issue, can we expect in the near future the implementation based on GsonSerializationSpec annotation?

@frankiesardo

This comment has been minimized.

Show comment
Hide comment
@frankiesardo

frankiesardo Jul 30, 2015

Owner

@johnkil I don't think so. But using @AutoGson as described here gets the job done.

Owner

frankiesardo commented Jul 30, 2015

@johnkil I don't think so. But using @AutoGson as described here gets the job done.

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Aug 11, 2015

I think this can be closed since the direction of AutoValue extensions will allow this to be accomplished with composition of extensions.

I think this can be closed since the direction of AutoValue extensions will allow this to be accomplished with composition of extensions.

@frankiesardo

This comment has been minimized.

Show comment
Hide comment
@frankiesardo

frankiesardo Aug 11, 2015

Owner

Agree. This is now out of scope.

Owner

frankiesardo commented Aug 11, 2015

Agree. This is now out of scope.

@luoser luoser referenced this issue in kickstarter/android-oss Feb 17, 2017

Merged

Instrument updates, add KoalaContext #59

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment