Giter VIP home page Giter VIP logo

auto-value-gson's People

Contributors

3flex avatar ansman avatar autonomousapps avatar bejibx avatar bryanstern avatar cushon avatar dmitry-timofeev avatar eamonnmcmanus avatar ersin-ertan avatar fabiocollini avatar gabrielittner avatar jakekdodd avatar jakewharton avatar jettbow avatar jffiorillo avatar kmenager avatar lgawin avatar luciofm avatar mik9 avatar mseele avatar nightlynexus avatar oguzbabaoglu avatar piasy avatar prempalsingh avatar rharter avatar ronshapiro avatar timfreiheit avatar xmiketx avatar zacsweers avatar zsavely avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

auto-value-gson's Issues

Compilation error if AutoValue class has toBuilder method

If AutoValue class has toBuilder method to initialize a builder to the same property values as an existing value instance(#to_builder), generated constructor for AutoValue_CommentModel has one redundant parameter: CommentModel.Builder toBuilder

Example:

@AutoValue
public abstract class CommentModel {
    ...
    public abstract Builder toBuilder();
    ...

Generated class:

final class AutoValue_CommentModel extends $AutoValue_CommentModel {
    AutoValue_CommentModel(..., CommentModel.Builder toBuilder) {
        super(..., toBuilder);
    }
...

Add support for custom TypeAdapters

I need to modify some fields before sending my objects and after parsing them. More precisely, I convert from epoch seconds to epoch milliseconds and viceversa.

Before adding auto-value I was using custom TypeAdapters to do this conversion, but I can't do that anymore, since AutoValue_Foo.GsonTypeAdapter is final.

Ability to work with Hal JSON

Hi I was wondering how you think about adding functionality to handle support for HAL json, gson doesn't support it in a workable way. When you model all the classes as the json it works with gson but that means you would have to write a lot of model classes or really big model classes. There is a library halarious that works with gson to enable parsing of hal json but it doesn't work properly with AutoValue gson since it works with runtime reflection and adding JsonSerializer/JsonDeserializer for the same classes as the generated AutoValue. This defeats the purpose of creating the generated streaming parsers in the TypeAdapters.

I forked your extension and added 2 Annotations that are basically copies of SerializedName when adding those to your abstract methods instead of the SerializedName the code generation is a little bit different.

Do you think this would be a nice functionality to have or do you have other recommendations to get this working?

NoSuchMethodError com.squareup.javapoet.TypeSpec.classBuilde on 0.3.1

After upgrading to 0.3.1, building the project throws this error

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> java.lang.NoSuchMethodError: com.squareup.javapoet.TypeSpec.classBuilder(Lcom/squareup/javapoet/ClassName;)Lcom/squareup/javapoet/TypeSpec$Builder;

Reverting to 0.2.5 fixes the issue. These are the build.gradle lines concerning auto-value

apt 'com.ryanharter.auto.value:auto-value-gson:0.3.1'
apt 'com.ryanharter.auto.value:auto-value-parcel:0.2.1'
apt 'com.google.auto.value:auto-value:1.2'
provided 'com.google.auto.value:auto-value:1.2'
provided 'javax.annotation:jsr250-api:1.0'

There are many more dependencies (retrofit2, picasso, rx, etc.). Let me know if you need the full list.

Thanks!

Support mechanism to exclude some classes

Default behavior of this extension is create TypeAdapterFactory for every AutoValue classes. But maybe not all of AutoValue classes need it. So it'd be great if we have a mechanism to exclude or include a specific AutoValue class. A @gson Annotation is a good idea.

Generated TypeAdapters using Reflection

The TypeAdapterFactories generated by auto-value-gson are using reflection, which is inefficient on Android. Since Android apps usually need to register type adapter factories at application start up this causes a significant delay in app start up.

For example for List<String> the following is generated in the TypeAdapterFactories constructor:
stringAdapter = gson.getAdapter(new TypeToken<List<String>(){})

Inside the default TypeToken constructor is where the reflection happens:
this.type = getSuperclassTypeParameter(getClass());

A better way would be to create an instance of java.lang.reflect.ParameterizedType and pass it into gson.getAdapter(). Unfortunately the only implementations of java.lang.reflect.ParameterizedType are either in Guava or are in internal packages in Gson. In Gson you can create one by calling com.google.gson.internal.$Gson$Types#newParameterizedTypeWithOwner(null, List.class, String.class). Again this is an internal class so probably don't want to rely on it.

The only other solution would be to create an implementation of ParameterizedType and use it. This would have to be a compile time dependency of the client library or application.

Here is a hacky method I created that would use the com.google.gson.internal.$Gson$Types#newParameterizedTypeWithOwner(null, List.class, String.class) solution. Unfortunately it doesn't handle more complicated scenarios where the ParameterizedType includes another ParameterizedType like List<Set<String>> or Map<String, Set<String>>

private CodeBlock getParameterizedTypeConstructorStatement(ParameterizedTypeName type, FieldSpec field, ParameterSpec gsonParam) {
    CodeBlock.Builder block = CodeBlock.builder();
    try {
      int typeArgsSize = type.typeArguments.size();
      int argsIndex = 0;
      Object[] args = new Object[5 + (typeArgsSize)];
      args[argsIndex++] = field;
      args[argsIndex++] = type;
      args[argsIndex++] = gsonParam;
      args[argsIndex++] = ClassName.get($Gson$Types.class);
      args[argsIndex++] = type.rawType;
      String[] genericTypesFormatWithClass = new String[typeArgsSize];
      for (int i = 0; i < typeArgsSize; i++) {
        args[argsIndex++] = type.typeArguments.get(i);
        genericTypesFormatWithClass[i] = "$T.class";
      }
      StringBuilder blockString = new StringBuilder("this.$N = (TypeAdapter<$T>) $N.getAdapter(TypeToken.get($T.newParameterizedTypeWithOwner(null,$T.class,");
      Joiner.on(",").appendTo(blockString, genericTypesFormatWithClass);
      blockString.append(")))");
      block.addStatement(blockString.toString(), args);
    }catch (Exception e){
      //Fall back on using reflection
      block.addStatement("this.$N = $N.getAdapter(new TypeToken<$T>(){})", field,gsonParam, type);
    }

How would I go about using an ExclusionStrategy of a custom annotation targeted to a Field?

Trying to do something along the lines of:

    // The fields I want to exclude from serialization/deserialization 
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.METHOD}) // FIXME: remove method
    public @interface Exclude {
    }
    public static class ExcludeAnnotationExclusionStrategy implements ExclusionStrategy {
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getAnnotation(Exclude.class) != null;
        }

        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    }
    Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(new AutoValueTypeAdapterFactory())
            .serializeNulls()
            .setExclusionStrategies(new ExcludeAnnotationExclusionStrategy())
            .create();

I tried simply implementing the derived property style where I define the field in the abstract class with its own accessor method and annotate this property with @Exclude, but this doesn't work as it is not included in the generated GsonTypeAdapter. Also, it will not be included in the generated parcelable implementation using auto-value-parcel.

Generics with parameterized fields

A model with a parameterized field such as this one:

@AutoValue
public abstract class ListResponse<T> {
  public abstract List<T> results();
}

Will produce:

this.resultsAdapter = gson.getAdapter(new TypeToken<List<T>>(){});

This doesn't work since T is erased during runtime.

Boolean: is naming convention: Cannot find symbol

I have a very simple class:

@AutoValue public abstract class PurchaseStateModel {

    @NonNull public static PurchaseStateModel of(boolean isPurchased) {
        return new AutoValue_PurchaseStateModel(isPurchased);
    }

    public abstract boolean isPurchased();
}

Which causes an exception at compile time. It transformed "isPurchased" to "purchased".

@Override
    public void write(JsonWriter jsonWriter, PurchaseStateModel object) throws IOException {
      jsonWriter.beginObject();
      jsonWriter.name("purchased");
      purchasedAdapter.write(jsonWriter, object.purchased());
      jsonWriter.endObject();
    }

Causes to generate TypeAdapter

First of all, thank you for the #19—it greatly simplified things. Just wanted to ask—is it possible to eliminate the need of static method returning TypeAdapter? For example, the processor can go over the class signature and detect if any methods have @SerializedName annotation and, if it does, generate TypeAdapter automagically. It is not an ideal solution of course because @SerializedName is not mandatory at this point. Wanted to ask about this because after #19 implementation it feels a little cumbersome to keep a static method in every model.

Make it work with @JsonAdapter

Given model class:

@AutoValue
@JsonAdapter(AutoValue_Item.ItemTypeAdapter.class)
public abstract class Item {
  public static Builder builder() {
    return new AutoValue_Item.Builder();
  }

  public abstract long id();
  public abstract String name();

  @AutoValue.Builder
  public static abstract class Builder {
    public abstract Builder id(long id);
    public abstract Builder name(String name);
    public abstract Item build();
  }
}

Following test will fail:

public class ItemTest {
  @Test public void gson() {
    final Item i0 = Item.builder().id(1).name("Awesome!").build();
    final Gson gson = new Gson();
    final String json = gson.toJson(i0);
    final Item i1 = gson.fromJson(json, Item.class); // Will fail!
    assertThat(i1).isEqualTo(i0);
  }
}

With stack trace:

java.lang.NullPointerException
    at com.thuytrinh.android.autosamples.AutoValue_Item$ItemTypeAdapter.read(AutoValue_Item.java:61)
    at com.thuytrinh.android.autosamples.AutoValue_Item$ItemTypeAdapter.read(AutoValue_Item.java:32)
    at com.google.gson.Gson.fromJson(Gson.java:861)
    at com.google.gson.Gson.fromJson(Gson.java:826)
    at com.google.gson.Gson.fromJson(Gson.java:775)
    at com.google.gson.Gson.fromJson(Gson.java:747)

ZipException in IntelliJ/Android Studio multiple modules

If I have two IntelliJ/Studio modules, both containing AutoValue classes, and one depends on the other. The generated com.ryanharter.auto.value.gson.AutoValueGsonTypeAdapterFactory class is present in both the modules and this causes a ZipException when building the project.

Gson 2.4 now supports @SerializedName on methods, description should be updated

Since recent release gson-2.4, it supports @SerializedName on methods (see CHANGELOG).

So I guess this part of README.md should be updated somehow:

Note: Since Gson's built in SerializedName annotation can't be used on methods, you'll have to change your SerializedName import to com.ryanharter.auto.value.gson.SerializedName.

I am not sure how exactly you want to handle this - either by dropping your version of @SerializedName and removing respective note from README or by leaving this custom annotation for those who use earlier Gson version and just mentioning that since gson-2.4 it is not needed.

So I didn't send PR :)

Android Studio multiple modules- NoClassDefFoundError Parcelable

I couldn't figure out what's causing this. I have a 3 module project two of which have the third as a dependency. When I build module_one everything works fine, but when I try building module_two I get this weird error. Running with stacktrace makes me guess that android/os/Parcelable should've been android.os.Parcelable.

Anyone else faced this before?

:module_two:compileMockDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':consumer:compileMockDebugJavaWithJavac'.
> java.lang.NoClassDefFoundError: android/os/Parcelable

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':consumer:compileMockDebugJavaWithJavac'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:66)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: java.lang.RuntimeException: java.lang.NoClassDefFoundError: android/os/Parcelable
    at com.sun.tools.javac.main.Main.compile(Main.java:553)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:46)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:104)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:53)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:35)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25)
    at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:163)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:145)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:93)
    at com.android.build.gradle.tasks.factory.AndroidJavaCompile.compile(AndroidJavaCompile.java:49)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:245)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:232)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    ... 14 more
Caused by: java.lang.NoClassDefFoundError: android/os/Parcelable
    at com.ryanharter.auto.value.gson.AutoValueGsonExtension.getDefaultValue(AutoValueGsonExtension.java:465)
    at com.ryanharter.auto.value.gson.AutoValueGsonExtension.createReadMethod(AutoValueGsonExtension.java:380)
    at com.ryanharter.auto.value.gson.AutoValueGsonExtension.createTypeAdapter(AutoValueGsonExtension.java:312)
    at com.ryanharter.auto.value.gson.AutoValueGsonExtension.generateClass(AutoValueGsonExtension.java:185)
    at com.google.auto.value.processor.AutoValueProcessor.writeExtensions(AutoValueProcessor.java:474)
    at com.google.auto.value.processor.AutoValueProcessor.processType(AutoValueProcessor.java:460)
    at com.google.auto.value.processor.AutoValueProcessor.process(AutoValueProcessor.java:150)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    ... 34 more
Caused by: java.lang.ClassNotFoundException: android.os.Parcelable
    ... 49 more


BUILD FAILED

Total time: 4.085 secs

parameterized types

code with parameterized types, for example a Map results in:
gson.getAdapter(Map<String, String>.class).write(jsonWriter, object.map());
and
map = gson.getAdapter(Map<String, String>.class).read(jsonReader);
which results in a compile time error

Would be useful to restrict serialization/deserialization with gson @Expose annotation

We conditionally expose fields in our models with the @Expose annotation. GsonBuilder can be configured to recognize. Is there a plan to enable this feature with auto-value-gson extension?

public class MyModel {
   private long doNotExpose;   
  @Expose @SerializedName("expose_me") private long exposeMe;  
...
}
final Gson gson = new GsonBuilder()
   .excludeFieldsWithoutExposeAnnotation()
...
   .create();

Support for Enum type

Hi,

I would like to know if there is a support for enum type with the library

@AutoValue
public abstract class Facility implements Parcelable {

    public enum Codes {
        @SerializedName("CPF") FREE,
        @SerializedName("COP") CHARGEABLE,
        @SerializedName("CPP") CHARGEABLE_ONSITE
    }

    @SerializedName("code")
    public abstract Codes code();

    @SerializedName("legend")
    public abstract String legend();

    @NonNull
    public static TypeAdapter<Facility> typeAdapter(Gson gson) {
        return new AutoValue_Facility.GsonTypeAdapter(gson);
    }
}

According to this answer http://stackoverflow.com/a/18851314 on stackoverflow, this is a valid syntax for Gson, but when I try it I get a null pointer exception.

Thanks

Add @SuppressWarnings to AutoValueGsonTypeAdapterFactory's method create

Hello, I'm getting compilation warnings about unchecked or unsafe casts whenever i use your library.

I did a pull request about what need to be changed but travis gives error on test, and it's ok because generated files changes.

Anyways, please consider add these lines to AutoValueGsonAdapterFactoryProcessor, under MethodSpec.Builder create = MethodSpec.methodBuilder("create"):

.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class)
.addMember("value", "$S", "unchecked")
.build())

Unsupported major.minor version 52.0

Hello,

Thanks for your great extensions.

But while trying auto-value-gson, I got an error during the build.

java.lang.UnsupportedClassVersionError: com/ryanharter/auto/value/gson/AutoValueGsonExtension : Unsupported major.minor version 52.0 

Here is my build.gradle AutoValue related content

final AutoValueVersion = '1.2-SNAPSHOT'
final AutoValueGson = '0.1-SNAPSHOT'
final AutoValueParcel= '0.2-SNAPSHOT'

compile "com.google.auto.value:auto-value:$AutoValueVersion"
apt "com.google.auto.value:auto-value:$AutoValueVersion"
apt "com.ryanharter.auto.value:auto-value-gson:$AutoValueGson"
apt "com.ryanharter.auto.value:auto-value-parcel:$AutoValueParcel"

Here is my class code

@AutoValue
public abstract class Partner implements Parcelable {
    public abstract String name();
    public abstract String logoUrl();
}

I'm using Java 7 JDK in my Android Project. And If I removed the AutoValue Gson extension, the class is generated without problems, that means I guess that the Gson extension is the problem.

Respect gson.serializeNulls()

The API I'm working with requires null attributes to be sent and the generated type adapter never writes attributes which are null.

ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast

I made model from example of WebResponse where i'm using Type parameter like so :

@AutoValue
public abstract class SocialStream<T> {
  public abstract int id();
  ......
  ......

  public abstract List<T> messages();

  public static <T> TypeAdapter<SocialStream<T>> typeAdapter(Gson gson, TypeToken<? extends SocialStream<T>> typeToken) {
    return new AutoValue_SocialStream.GsonTypeAdapter(gson, typeToken);
  }
}

As you can see i also passed typetoken to AutoValue typeAdapter, and everything seems to work, i already logged whole json, but problem occurs when i try to use it as my model.

SocialStream<FacebookPost> post = getList().get(0);

method getList() returns array of these messages and this is the line where i'm getting exception:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.model.FacebookPost

does it working on the customize nested object?

for example :

import android.os.Parcelable;
import com.google.auto.value.AutoValue;
import com.google.gson.annotations.SerializedName;

@AutoValue
public abstract class FbAlbum implements Parcelable {
    @SerializedName("id") public abstract String id();
    @SerializedName("name") public abstract String name();
    @SerializedName("count") public abstract int count();
    @SerializedName("picture") public abstract Picture picture();

    public static FbAlbum create(String id, String name, int count, Picture picture) {
        return new AutoValue_FbAlbum(id, name, count, picture);
    }

    public FbAlbum() {}

    @AutoValue
    public abstract static class Picture implements Parcelable {
        @SerializedName("data") abstract PictureData data();

        public static Picture create(String url) {
            return new AutoValue_FbAlbum_Picture(PictureData.create(url));
        }
    }

    @AutoValue
    public abstract static class PictureData implements Parcelable {
        @SerializedName("url") abstract String url();

        public static PictureData create(String url) {
            return new AutoValue_FbAlbum_PictureData(url);
        }
    }
}

I will get the error message at runtime

Process: com.cardinalblue.android.piccollage.multitouch.photoproto, PID: 28821
java.lang.RuntimeException: Failed to invoke public com.cardinalblue.android.piccollage.model.gson.FbAlbum$Picture() with no args
   at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:111)
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:206)
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116)
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216)
   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116)
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216)
   at com.google.gson.Gson.fromJson(Gson.java:879)
   at com.google.gson.Gson.fromJson(Gson.java:844)
   at com.google.gson.Gson.fromJson(Gson.java:793)
   at com.cardinalblue.android.utils.Utils.parseWithGson(Utils.java:500)
   at com.cardinalblue.android.utils.Utils.parseWithGson(Utils.java:468)
   at com.cardinalblue.android.piccollage.model.gson.FbJsonParser.parse(FbJsonParser.java:33)
   at com.cardinalblue.android.piccollage.model.gson.FbJsonParser.parseAlbums(FbJsonParser.java:22)
   at com.cardinalblue.android.piccollage.view.adapters.FbAlbumListAdapter.parseAlbumList(FbAlbumListAdapter.java:228)
   at com.cardinalblue.android.piccollage.view.adapters.FbAlbumListAdapter.access$300(FbAlbumListAdapter.java:36)
   at com.cardinalblue.android.piccollage.view.adapters.FbAlbumListAdapter$2.onCompleted(FbAlbumListAdapter.java:198)
   at com.facebook.GraphRequest$5.run(GraphRequest.java:1379)
   at android.os.Handler.handleCallback(Handler.java:739)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:148)
   at android.app.ActivityThread.main(ActivityThread.java:5417)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.InstantiationException: Can't instantiate abstract class com.cardinalblue.android.piccollage.model.gson.FbAlbum$Picture
   at java.lang.reflect.Constructor.newInstance(Native Method)
   at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:108)
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:206) 
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116) 
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216) 
   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) 
   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) 
   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) 
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116) 
   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216) 
   at com.google.gson.Gson.fromJson(Gson.java:879) 
   at com.google.gson.Gson.fromJson(Gson.java:844) 
   at com.google.gson.Gson.fromJson(Gson.java:793) 
   at com.cardinalblue.android.utils.Utils.parseWithGson(Utils.java:500) 
   at com.cardinalblue.android.utils.Utils.parseWithGson(Utils.java:468) 
   at com.cardinalblue.android.piccollage.model.gson.FbJsonParser.parse(FbJsonParser.java:33) 
   at com.cardinalblue.android.piccollage.model.gson.FbJsonParser.parseAlbums(FbJsonParser.java:22) 
   at com.cardinalblue.android.piccollage.view.adapters.FbAlbumListAdapter.parseAlbumList(FbAlbumListAdapter.java:228) 
   at com.cardinalblue.android.piccollage.view.adapters.FbAlbumListAdapter.access$300(FbAlbumListAdapter.java:36) 
   at com.cardinalblue.android.piccollage.view.adapters.FbAlbumListAdapter$2.onCompleted(FbAlbumListAdapter.java:198) 
   at com.facebook.GraphRequest$5.run(GraphRequest.java:1379) 
   at android.os.Handler.handleCallback(Handler.java:739) 
   at android.os.Handler.dispatchMessage(Handler.java:95) 
   at android.os.Looper.loop(Looper.java:148) 
   at android.app.ActivityThread.main(ActivityThread.java:5417) 

AutoValueGsonAdapterFactoryProcessor doesn't account for projects with multiple modules

AutoValueGsonAdapterFactoryProcessor generated a class called com.ryanharter.auto.value.gson.AutoValueGsonTypeAdapterFactory. This obviously doesn't work when auto-value-gson is used in multiple modules. It would be nice if auto-value-gson would either allow modules to change the package/class name via an annotation processor argument or have some other way to workaround this.

GsonTypeAdapterFactory not found

Android Studio can't find @GsonTypeAdapterFactory annotation.
I am using apt 'com.ryanharter.auto.value:auto-value-gson:0.4.0', I also have tried with apt 'com.ryanharter.autogson:auto-gson:0.1-SNAPSHOT' from maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }.

Not sure if I should use apt, provided or compile for importing.

Add support for field naming policies

Gson has support for different field naming policies which does not seem to work with this library. For example, by setting LOWER_CASE_WITH_UNDERSCORES while creating the gson object, all field names with lowercase and underscore separated format will automatically mapped to their camel case formats in the Java classes.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create();

public class Dog {
    public String makeNoise;
}

And its equivalent json:

{
    "make_noise": "bark"
}

We can use @SerializedName annotation for this but it becomes tedious if all the field names are to be converted from the same underscore format.

Ignore(BOTH) isn't respected

Provide an annotation that lets us specify the fields not to be included in the generated TypeAdapter for the @AutoValue annotated class.

For Example:

@AutoValue public abstract class Foo {
  @Gson.Ignore abstract String bar();
  @SerializedName("Baz") abstract String baz();

  // The public static method returning a TypeAdapter<Foo> is what
  // tells auto-value-gson to create a TypeAdapter for Foo.
  public static TypeAdapter<Foo> typeAdapter(Gson gson) {
    return new AutoValue_Foo.GsonTypeAdapter(gson);
  }
}

Generated Class:

public static final class GsonTypeAdapter extends TypeAdapter<Foo> {
    private final TypeAdapter<String> bazAdapter;
    public GsonTypeAdapter(Gson gson) {
      this.bazAdapter = gson.getAdapter(String.class);
    }

   // ...
}

JSON field annotation

If it is not possible to use the SerializedName annotation from Gson itself, why not use something (probably) better named? Like Json from Moshi.

giphy

Support single TypeAdapterFactory for all AutoValue generated type adapters.

The currently TypeAdapterFactory mechanism requires users to add each individual TypeAdapterFactory to each Gson instance in order to de/serialize objects. This can be cumbersome, especially when you have a large number of model objects.

As long as we're already generating code, we could alleviate this by generating a single AutoValueTypeAdapterFactory that will serve as TypeAdapterFactory for all AutoValue: Gson generated type adapters. This can use the standard TypeAdapterFactory mechanism to check the class type and delegate the request to the appropriate TypeAdapter.

The challenge I see here is that the AutoValue Extension mechanism processes classes serially, meaning this would require an additional annotation process that processes the same @AutoValue annotation, checks applicability, and generates a single AutoValueTypeAdapterFactory for all applicable classes.

This would reduce the code needed to configure your Gson instance to the following:

Gson gson = new GsonBuilder()
  .registerTypeAdapterFactory(new AutoValueTypeAdapterFactory())
  .build();

Generated TypeAdapterFactory and null safety

As of 0.2.5, My custom AutoValueTypeAdapterFactory would call nullSafe() on every type adapter I return in the create() method. Refer #28 (comment).

Class<? super T> rawType = type.getRawType();
if (rawType.equals(User.class)) {
    return (TypeAdapter<T>) User.typeAdapter(gson).nullSafe();
}

Beginning from 0.3.0, the generated AutoValueGsonTypeAdapterFactory does not call nullSafe() by default, which is the appropriate way for sure.

So, how'd I go about ensuring null-safety when using the generated TypeAdapterFactory.

What should the default collection policy be?

Recently the functionality of collections was changed to default to empty collections, instead of null (#71), but this technically breaks the contract with AutoValue, since the property is not annotation with @Nullable. That means that it should technically exist in the JSON. This potentially masks JSON encoding issues.

IMHO, the issue here is that deserializing and serializing are now no longer compatible, i.e. if you deserialize JSON that has a null collection property then serialize it using this extension, you won't be able to reproduce the original JSON, potentially with different meaning.

Recognizing the usefulness of this functionality, @hzsweers has proposed making this a non-default option configurable using apt arguments. This ticket is to discuss the implications and determine what the default collection policy should be.

Ship a default "MyAdapterFactory" with `auto-value-gson`.

Can a default, "basic", TypeAdapterFactory be shipped with auto-value-gson? Such as the one from https://github.com/rharter/auto-value-gson#factory.

Code:

@GsonTypeAdapterFactory
public abstract class MyAdapterFactory implements TypeAdapterFactory {

  // Static factory method to access the package
  // private generated implementation
  public static TypeAdapterFactory create() {
    return new AutoValueGson_MyAdapterFactory();
  }

}

Generated Code:

public final class AutoValueGson_MyAdapterFactory extends MyAdapterFactory {
  @Override
  @SuppressWarnings("unchecked")
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<T> rawType = (Class<T>) type.getRawType();
    if (Media.class.isAssignableFrom(rawType)) {
      return (TypeAdapter<T>) Media.typeAdapter(gson);
    } else {
      return null;
    }
  }
}

We can add a new module with this class to add to the compile configuration.

Support toBuilder method

AutoValue-gson generates a class which does not compile when I have a toBuilder method in my class. It seems to confuse it for a property and generates an constructor for it:

@AutoValue public abstract class Foo {

    abstract long id();

    public static TypeAdapter<Foo> typeAdapter(Gson gson) {
        return new AutoValue_Foo.GsonTypeAdapter(gson);
    }

    abstract Builder toBuilder();

    @AutoValue.Builder
    static abstract class Builder {
        abstract Builder id(long id);
        abstract Foo build();
    }
}

Problem with Generics and AdapterFactory

If I add the example with generics to my code:

@AutoValue
public abstract class Foo<A, B, C> {
    // properties...

    public static <A, B, C> TypeAdapter<Foo<A, B, C>> typeAdapter(Gson gson,
                                                                  TypeToken<? extends Foo<A, B, C>> typeToken) {
        return new AutoValue_Foo.GsonTypeAdapter(gson, typeToken);
    }
}

I have this error on my AdapterFactory:

/path/app/build/generated/source/apt/staging/debug/package/AutoValueGson_MyAdapterFactory.java
Error:(33, 78) error: cannot find symbol class A
Error:(33, 81) error: cannot find symbol class B
Error:(33, 84) error: cannot find symbol class C

To fix it I must change TypeToken<? extends Foo<A, B, C>> typeToken to TypeToken<? extends Foo> typeToken:

@AutoValue
public abstract class Foo<A, B, C> {
    // properties...

    public static <A, B, C> TypeAdapter<Foo<A, B, C>> typeAdapter(Gson gson,
                                                                  TypeToken<? extends Foo> typeToken) {
        return new AutoValue_Foo.GsonTypeAdapter(gson, typeToken);
    }
}

What's the problem? The example? Am I missing anything? Is my "fix" correct?

Problems when using with auto-value-parcel

Whe I use this auto-value-gson version 0.3.1 together with auto-value-parcel 0.2.1 I end with exception with multiple warnings before. Probably trying to process parcelable methods as well?

When I revert to verzion 0.2.5 of auto-value-gson it works fine. But I expected TypeAdapterFactory to be generated by the new version.

warning: @autovalue classes cannot have abstract methods other than property getters and Builder converters

Caused by: java.lang.NoSuchMethodError: com.squareup.javapoet.TypeSpec.classBuilder(Lcom/squareup/javapoet/ClassName;)Lcom/squareup/javapoet/TypeSpec$Builder;
at com.ryanharter.auto.value.gson.AutoValueGsonAdapterFactoryProcessor.createTypeAdapterFactory(AutoValueGsonAdapterFactoryProcessor.java:82)
at com.ryanharter.auto.value.gson.AutoValueGsonAdapterFactoryProcessor.process(AutoValueGsonAdapterFactoryProcessor.java:67)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
at com.sun.tools.javac.main.Main.compile(Main.java:523)
... 88 more

Problem creating under a package with UpperCases

Hi,

I found this error this morning using it.

Reproduce Step:

  • Create a package named MyPackage
  • Create a autovalue MyPackage.MyAutoValue.class
@AutoValue public abstract class MyAutoValue {
    @SerializedName("test") public abstract String test();
    @SerializedName("test_2") public abstract String test2();

    public static MyAutoValue create() {
        return null;
    }
}

-> this compiles

  • add the TypeAdapter
@AutoValue public abstract class MyAutoValue {
    @SerializedName("test") public abstract String test();
    @SerializedName("test_2") public abstract String test2();

    public static MyAutoValue create() {
        return null;
    }

    public static TypeAdapter<MyAutoValue> typeAdapter(Gson gson) {
        return new AutoValue_TestAutoValueGson.GsonTypeAdapter(gson);
    }
}
Error:(8, 40) error: cannot find symbol class MyPackage
Error:(18, 78) error: package MyPackage does not exist
Error:(26, 59) error: package MyPackage does not exist
Error:(35, 25) error: package MyPackage does not exist

I had another error looking like this
Could not find best guess class for .MyPackage.MyAutoValue.class on line 144

   ClassName autoValueClass = ClassName.bestGuess(context.autoValueClass().getQualifiedName().toString());

How to avoid the problem using this release

Put all packages in lowercase

?

Does get qualified name is returning a path with lowercase and another package is looking to an uppercase path?

It was an error by my part using an uppercase in a package but I had hard time to pinpoint the problem.

I hope it helps

Serializing null AutoValue object

I am converting slowly my value objects to AutoValue with Gson extension.
I am having an issue for the following case:
(Pseudo code)

// Not an AutoValue (yet)
class A{
 B b;
}

@AutoValue
class B{
  public abstract Boolean enabled();

  public static TypeAdapter<B> typeAdapter(Gson gson) {
    return new AutoValue_B.GsonTypeAdapter(gson);
  }
}

When I am trying to serialize A with gson and B is null I am getting a NPE on the following line if (object.enabled() != null) inside $AutoValue_B:

    @Override
    public void write(JsonWriter jsonWriter, B object) throws IOException {
      jsonWriter.beginObject();
      if (object.enabled() != null) {
        jsonWriter.name("enabled");
        enabledAdapter.write(jsonWriter, object.enabled());
      }
      jsonWriter.endObject();
    }

because object is null.

Unable to Serialize null field

I have a need to serialize a null field. When I mark the field as @Nullable, I see the GsonTypeAdapter write(JsonWriter, Object) method wrap the field adapter's write() call in a null check. But if I remove @Nullable, my builder/factory methods complain about the null value. Is there any way around this?

It looks like 23 could be related?

For clarity, I am calling serializeNulls in my GsonBuilder. Perhaps the write method's GsonTypeAdapter could check that flag in the JsonWriter to bypass the above mentioned null check?

Android studio multiple modules and Generated TypeAdapterFactory

I've been using AutoValueGson 0.2.5 in my android project which consists of two modules A and B. B has a compile dependency on A, and both A and B contain AutoValue classes.

I created two TypeAdapterFactorys for both the modules: AFactory and BFactory. I, however, made BFactory extend AFactory so I could use it in GsonBuilder.registerTypeAdapterFactory(new BFactory()) and have all my AutoValue typeAdapters included.

The idea is that I can have module A be used by a certain module C and follow the same pattern.

I am not sure how 0.3.0's generated AutoValueGsonTypeAdapterFactorys in both modules can accommodate what I was doing with a custom Factory class.

buildUpon() not working

The generated constructor contains a field for a builder:

AutoValue_Message(String text, Message.Builder buildUpon) {
super(text, buildUpon);
}

(This results in a compile time error)

When use SerializedName

@AutoValue
public abstract class Topic {

    public abstract String getId();

    @SerializedName("lastupdate")
    public abstract String getLastUpdate();

    public static TypeAdapter<Topic> typeAdapter(Gson gson) {
        return new AutoValue_Topic.GsonTypeAdapter(gson);
    }
}

// in $AutoValue_Topic.java
...
jsonWriter.name("getId"); // "getId" This is not what I expect
...
jsonWriter.name("lastupdate");

Why "getId" is not "id"? How to fix it?

Possible to extend the deserializer to add additional custom value decoding?

Hi,
In my use case I have an auto-value object with that looks something like:

class Foo {
String a;
String b;
String c;
String d;
CustomObject e;
}

I'd like to extend the auto-value deserializer to automatically parse a,b,c,d but let me add additional logic to manually parse the CustomObject at the end.

Is this possible?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.