3

現在、次のクラスがあります。

 static final class TabInfo{
   public final String tag;
   public final Class<?> clss;
   public Bundle args;

   TabInfo(String _tag, Class<?> _class, Bundle _args) {
       tag = _tag;
       clss = _class;
       args = _args;
   }
 }

そのうちjsonを作成したいと思います。これを行うために、次のコードを使用しています。

 Gson gson= new Gson();
 Type hmType= new TypeToken<TabInfo>(){}.getType();
 String json = gson.toJson(methodToGetAnInstanceOfTabInfoClassHere, hmType);

これを行っているときに、java.lang.StackOverFlowError が発生します。

E/AndroidRuntime(10353):    at Java.lang.StringBuffer.append(StringBuffer.java:219)
E/AndroidRuntime(10353):    at java.io.StringWriter.write(StringWriter.java:147)
E/AndroidRuntime(10353):    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:519)
E/AndroidRuntime(10353):    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:387)
E/AndroidRuntime(10353):    at com.google.gson.stream.JsonWriter.beginObject(JsonWriter.java:300)
E/AndroidRuntime(10353):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:190)
E/AndroidRuntime(10353):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrap    E/AndroidRuntime(20692):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)

だから、私の質問は次のとおりです:スタックオーバーフローエラーを取得せずに、クラス TabInfo から Java オブジェクトの有効な json を作成するように gson を取得するにはどうすればよいですか?

ところで。ご覧のとおり、私はこれまでそれほど多くの質問をしたことがありません。質問を改善する方法についてフィードバックがあれば、お知らせください。

編集 1: バンドル クラスは標準バンドルです。fi: Bundle args = new Bundle(); args.putint("someint", 1);

更新されたスタックトレースを参照してください...

編集 2: String.class を引数として使用して、TabInfo の単一のインスタンスを取得する場合、たとえば:

  TabInfo test= new TabInfo("test", String.class, new Bundle());
  String result=gson.toJson(test, hmType);

次に、次のスタックトレースを取得します。

E/AndroidRuntime(22068): java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: java.lang.String. Forgot to register a type adapter?
E/AndroidRuntime(22068):    at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:64)
E/AndroidRuntime(22068):    at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
E/AndroidRuntime(22068):    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
E/AndroidRuntime(22068):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(22068):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
E/AndroidRuntime(22068):    at com.google.gson.Gson.toJson(Gson.java:586)
E/AndroidRuntime(22068):    at com.google.gson.Gson.toJson(Gson.java:565)
E/AndroidRuntime(22068):    at com.google.gson.Gson.toJson(Gson.java:520)

これは、TabInfo クラスの一部である可能性のある 24 の異なるクラスすべてに対して TypeToken を作成する必要があるということですか? これを解決するにはどうすればよいですか?

編集 3

OK、@Zaske のおかげで、問題の最初の部分の修正が見つかりました。以下に示すように、別のクラス署名を使用する

static final class TabInfo{
 TabInfo(String _tag, String _class, Bundle _args) {
   tag = _tag;
   clss = _class;
   args = _args;
 }

}

これで json を作成できますが、実際の HashMap < String, < Stack < TabInfo > > > を作成してこれを実行しようとすると、再び問題が発生します。その場合に使用するタイプトークンは次のとおりです。

 Type hmType = new TypeToken<HashMap<String, Stack<TabInfo>>>(){}.getType();

それで、私の最後の質問は、ハッシュマップ内の一連のタブ情報スタックをjsonに変換するにはどうすればよいですか?

編集 4 ここにいくつかの詳細情報があります: 使用される Bundle クラスは、アクティビティとフラグメントに引数を提供するために Android で使用される Bundle クラスです。( http://developer.android.com/reference/android/os/Bundle.htmlを参照)

私が行った場合

 TabInfo test= new TabInfo("test", "String", new Bundle());
 //stage 1 test
 String result=gson.toJson(test);
 Log.d("new result=",result);

次に、Json 出力を取得します (以下を参照)。

 D/new result=(20816): {"args":{"mClassLoader":{"packages":{}},"mMap":{},"mHasFds":false,"mFdsKnown":true,"mAllowFds":true},"clss":"String","tag":"test"}

ただし、TabInfo クラスからスタックの Hashmap を作成しようとすると、壊れます (メモリが不足します...)...

4

1 に答える 1

2

「クラスから文字列への変更」を提案したので
、読者のために、最初の部分についてここで回答することを許可します。
クラスをフィールドとして使用しないでください。ただし、完全なクラス名を含む文字列を使用する
必要がありますのように見える:

static final class TabInfo{
   public final String tag;
   public final String clss;
   public Bundle args;

   TabInfo(String _tag, Class<?> _class, Bundle _args) {
       tag = _tag;
       clss = _class.getName();
       args = _args;
   }
 }




2 番目の部分について:
Bundle クラスが何であるかわかりません。情報を提供してください
。少し変更して、実験用に独自のクラスを作成する必要がありました。

人物クラスは次のとおりです。

public class Person implements Serializable {
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public Person() {

    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    private String name;
    private int age;
}

チェックする主なクラスは次のとおりです。

public class Main {
    public static void main(String[] args) {
        Type type = new TypeToken<HashMap<String,Stack<Person>>>(){}.getType();
        Gson gson = new Gson();
        HashMap<String,Stack<Person>> map = new HashMap<String, Stack<Person>>();
        map.put("yair", new Stack<Person>());
        map.get("yair").add(new Person("Yair",36));
        String str = gson.toJson(map,type);
        System.out.println(str);
        map = gson.fromJson(str,type);
        String str2 = gson.toJson(map,type);
        System.out.println(str2);

    }
}

気軽に実行してみてください。str と str2 の両方が正常に出力されることがわかります。

更新
Bundle クラスをチェックしたところ、単純な引数のコレクションであるには (私の謙虚な意見では) あまりにも多くの情報が含まれていることがわかりました。
上記の質問で、代わりに単純なコレクションを使用できない理由がわかりません。
シリアル化には、できるだけ最小限のデータを含める必要が
あります (シリアル化されたデータを取得してストレージ デバイスに保存したり、ネットワーク経由で送信したりする場合を考えてください)。したがって、Bundle がコレクションにはない特別な機能を提供しない限り、使用しないでください。
経験則として、Json ですべてをシリアル化することはできないことを覚えておいてください。制限があります (たとえば、再帰的なデータ型)。そのため、ある型から JSON でシリアル化可能な型に変換する必要がある場合があります。
このパターンは他の場合にも使用されます。データ転送オブジェクト について詳しく読むことをお勧めします

于 2012-11-20T03:08:12.117 に答える