Gson.toJson дает StackOverFlowError, как получить правильный json в этом случае? (открытый статический класс)

В настоящее время у меня есть следующий класс:

 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)

Итак, мой вопрос: как я могу заставить мой gson создать действительный json из java-объектов из класса TabInfo без получения stackoverflowerror?

Btw. как вы все видите, я не задавал много вопросов раньше, поэтому, если у вас есть обратная связь для меня о том, как улучшить мой вопрос: дайте мне знать!

РЕДАКТИРОВАТЬ 1: Класс расслоения является стандартным расслоением, fi:    Bundle args = new Bundle();    args.putint( "someint", 1);

См. обновленную stacktrace...

ИЗМЕНИТЬ 2: Если я беру один экземпляр TabInfo, используя String.class в качестве аргумента, например:

  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)

Означает ли это, что мне нужно сделать TypeToken для всех 24 разных классов, которые могут быть частью класса TabInfo? Как это разрешить?

Изменить 3

Хорошо, спасибо @Zaske, я нашел исправление для первой части моей проблемы. Использование другой подписи класса, как показано ниже

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

}

Теперь я могу сделать json из него, но, когда я пытаюсь сделать это, создав фактический HashMap < String, < Stack < TabInfo → > Затем я снова сталкиваюсь с проблемами. В этом случае я использую typetoken:

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

Итак, теперь мой последний вопрос: как я могу преобразовать набор tabinfo-стеков в hashmap в json?

Изменить 4 Вот еще информация: Используемый класс Bundle - это класс Bundle, используемый в Android, для аргументов в отношении действий и фрагментов. (См. 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"}

Однако, когда я пытаюсь сделать Hashmap стеков из классов TabInfo, тогда он ломается (у него заканчивается память...)...

Ответ 1

Как я предложил "изменить класс" на строку,
я позволю себе ради наших читателей ответить здесь для первой части:
Не используйте Class как поле, но используйте String, который будет содержать полное имя класса
TabInfo должен выглядеть так:

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;
   }
 }

на
Относительно второй части:
Я не знаю, что такое класс Bundle - пожалуйста, предоставьте информацию,
так как мне пришлось немного изменить и написать собственный класс для эксперимента.

Класс Person:

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-сериализуемый тип.
Этот шаблон также используется в других случаях, я предлагаю вам больше узнать о объектах передачи данных