2016-10-19 15 views
1

getter/setterParcelable과 같은 내용에 AutoValue을 사용하고 있습니다.AutoValue를 사용할 때 JSON을 ArrayList로 변환 할 수 없습니다.

개체의 JSON 값을 SharedPreferences에 저장하고 필요할 때 검색 중입니다. 그러나, Constructor을 사용하는 것을 허용하지 않기 때문에 AutoValue을 사용하고 있기 때문에, 문자열로 저장된 JSON 배열을 SharedPreferencesArrayList<T>으로 변환하려고하면이 예외가 throw됩니다.

package org.yadavvi.tutorials.governor.data; 


import com.google.auto.value.AutoValue; 
import com.google.gson.Gson; 
import com.google.gson.TypeAdapter; 
import com.google.gson.annotations.SerializedName; 

/** 
* Immutable Governor created using AutoValue. 
*/ 
@AutoValue 
public abstract class Governor { 

    public static Governor create(String name) { 
     return new AutoValue_Governor(name); 
    } 

    @SerializedName("name") 
    abstract String name(); 
} 

여기에 내가 JSON 배열을 변환 할 경우 어떻게 클래스입니다 - 여기

java.lang.RuntimeException: Failed to invoke public org.yadavvi.tutorials.governor.data.Governor() 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.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.Gson.fromJson(Gson.java:879) 
at com.google.gson.Gson.fromJson(Gson.java:844) 
at com.google.gson.Gson.fromJson(Gson.java:793) 
at org.yadavvi.tutorials.governor.data.source.local.GovernorLocalDataSource.getGovernors(GovernorLocalDataSource.java:60) 
at org.yadavvi.tutorials.governor.data.source.local.GovernorLocalDataSourceTest.getGovernors_callsOnSuccessOfGetGovernorsCallback(GovernorLocalDataSourceTest.java:69) 

.... 

Caused by: java.lang.InstantiationException: Can't instantiate abstract class org.yadavvi.tutorials.governor.data.Governor 
at java.lang.reflect.Constructor.newInstance(Native Method) 
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:108) 
... 41 more 

Model/AutoValue 클래스처럼 보이는 방법입니다 - 여기

내가 점점 오전 예외 문자열을 ArrayList<T>처럼 보임 -

package org.yadavvi.tutorials.governor.data.source.local; 


import android.content.Context; 
import android.content.SharedPreferences; 
import android.support.annotation.NonNull; 
import android.util.Log; 

import org.yadavvi.tutorials.governor.data.Governor; 
import org.yadavvi.tutorials.governor.data.source.GovernorDataSource; 
import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.reflect.TypeToken; 

import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 


public class GovernorLocalDataSource implements GovernorDataSource { 

    .... 

    @Override 
    public void getGovernors(@NonNull GetGovernorsCallback callback) { 
     Gson gson = new GsonBuilder().create(); 
     List<Governor> governors; 

     String governorsString = mSharedPreference.getString(GOVERNORS, ""); 
     Log.i(TAG, "governorsString: " + governorsString); 
     if (governorsString.equalsIgnoreCase("")) { 
      governors = populateGovernors(); 
      governorsString = gson.toJson(governors); 
      mSharedPreference.edit().putString(GOVERNORS, governorsString).commit(); 
     } else { 
      governors = gson.fromJson(governorsString, new TypeToken<ArrayList<Governor>>(){}.getType()); 
     } 

     if (governors != null && governors.size() > 0) { 
      callback.onSuccess(governors); 
     } else { 
      callback.onFailure(); 
     } 
    } 

    .... 

} 

예외 내 Android 프로젝트의 일부 AutoValue-Extensions 있습니다


편집

governors = gson.fromJson(governorsString, new TypeToken<ArrayList<Governor>>(){}.getType()); 

-이 라인에서 던져 s의.

build.gradle은 다음과 같습니다 응용 프로그램 - 당신이 구상 클래스를 사용할 필요가

은 아래 링크
apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 24 
    buildToolsVersion "24.0.2" 
    defaultConfig { 
     applicationId "org.yadavvi.tutorials.governor" 
     minSdkVersion 21 
     targetSdkVersion 24 
     versionCode 1 
     versionName "1.0" 
     testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 
    } 
    buildTypes { 
     release { 
      minifyEnabled false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
     } 
    } 
} 

dependencies { 
    compile fileTree(include: ['*.jar'], dir: 'libs') 
    testCompile 'junit:junit:4.12' 
    testCompile 'org.mockito:mockito-core:2.2.5' 
    testCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
     exclude group: 'com.android.support', module: 'support-annotations' 
    }) 

    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
     exclude group: 'com.android.support', module: 'support-annotations' 
    }) 
    androidTestCompile 'org.mockito:mockito-core:2.2.5' 

    compile 'com.android.support:appcompat-v7:24.2.1' 
    compile 'com.google.auto.value:auto-value:1.2' 
    compile 'com.ryanharter.auto.value:auto-value-gson:0.4.3' 
} 

답변

1

나는 GsonBuilder에 사용자 정의 TypeAdapterFactory을 추가하고 그것을 잘 작동하는 것 같다.

package org.yadavvi.tutorials.governor.data; 

import com.google.gson.typeadapterfactory; 
import com.ryanharter.auto.value.gson.gsontypeadapterfactory; 

@GsonTypeAdapterFactory 
public abstract class GovernorAdapterFactory implements TypeAdapterFactory { 

    public static GovernorAdapterFactory create() { 
     return new AutoValueGson_GovernorAdapterFactory(); 
    } 

} 

GovernorLocalDataSource은과 같이 변경됩니다 - -

TypeAdapterFactory은 다음과 같이 보이는

public class GovernorLocalDataSource implements GovernorDataSource { 

    @Override 
    public void getGovernors(@NonNull GetGovernorsCallback callback) { 
     Gson gson = new GsonBuilder() 
       .registerTypeAdapterFactory(GovernorAdapterFactory.create()) 
       .create(); 
     List<Governor> governors; 

     String governorsString = mSharedPreference.getString(GOVERNORS, EMPTY_STRING); 
     if (governorsString.isEmpty()) { 
      governors = populateGovernors(); 
      governorsString = gson.toJson(governors); 
      mSharedPreference.edit().putString(GOVERNORS, governorsString).commit(); 
     } else { 
      Type type = new TypeToken<ArrayList<Governor>>() {}.getType(); 
      governors = gson.fromJson(governorsString, type); 
     } 

     if (governors != null && governors.size() > 0) { 
      callback.onSuccess(governors); 
     } else { 
      callback.onFailure(); 
     } 

    } 

} 

PS : 사람이 을 설명 할 수 있다면 그것은 좋은 것입니다 이 작품.

+1

이것은 Gson Auto Value 확장 기능의 문서에 대한 설명입니다. Gson에 AdapterFactory를 지정해야합니다. 그렇지 않으면 그것은 추상이기 때문에 반영 할 수없는 Governor 객체를 생성하려고 시도합니다. 확장에 의해 생성 된 어댑터 팩토리는 기본 클래스 대신 Governor의 AutoValue 구현을 사용하도록 지시합니다. –

+0

@JulienArzul 감사합니다! 'TypeAdapter'와'TypeAdapterFactory'를 설명하려고하는 [article] (http://federico.defaveri.org/2013/07/07/gson-custom-serialization-falling-in-default-serialization/)을 읽었습니다. 나는 지금 그것을 얻는다라고 생각한다.나는 또한'AutoValue'에서 생성 된 코드를 보았고'jsonReader.nextName()'이'name'이 아닌 경우'next value '를 건너 뛰는 것과 같이 많은 일을합니다. –

관련 문제