当前位置: 首页 > 知识库问答 >
问题:

格森。toJson给出StackOverFlowError,在这种情况下如何获得正确的json?(公共静态类)

暴奕
2023-03-14

我目前有以下课程:

 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 从类 TabInfo 创建 java 对象的有效 json,而不会收到堆栈溢出错误?

顺便说一句。正如你们所看到的,我以前没有问过那么多问题,所以如果你对如何改进我的问题有任何反馈,请告诉我!

编辑1:bundle类是标准Bundle,fi:Bundle args = new Bundle();args.putint("someint ",1);

请参阅更新的堆栈跟踪...

编辑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)

这是否意味着我需要为可能是TabInfo类一部分的所有24个不同类制作一个TypeToken?我该如何解决这个问题?

编辑3

好的,感谢@Zaske,我找到了解决问题第一部分的方法。使用另一个类签名,如下所示

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

}

现在我可以从中创建json,但是,当我尝试通过创建实际的HashMap来实现这一点时

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

所以,现在我的最后一个问题是:如何将hashmap中的一组tabinfo-stacks转换成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时,它会崩溃(它会运行内存溢出…)…

共有2个答案

云俊名
2023-03-14

我想到的另一个情况是,我在序列化类中持有 Dialog 的引用。在将类编写为首选项时会引发异常。

避免这种情况的修复是使用瞬态关键字使特定字段不可序列化(该特定解决方案的 SO 链接)。

示例代码:

public class Player implements Serializable { 
    private int id;
    private String name;
    private String slug;

    @Nullable
    transient Dialog prevDialogWeakRef;//non-serialised object

    // set getters()/setters()
}
越信鸥
2023-03-14

正如我建议将“从类”改为字符串一样,< br >为了我们的读者,我允许自己在这里回答第一部分:< br >不要将类用作字段,而是使用包含完整类名的字符串< br> TabInfo应该是这样的:< br >

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

< br>关于第二部分:< br >我不知道什么是Bundle类——请提供信息,< br >因为我不得不做了一点修改并编写了自己的实验类。< br>

人员类别为:

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

用于检查的主类是:< br >

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可序列化类型。
这种模式也用于其他情况,我建议您阅读更多关于数据搬迁对象的信息

 类似资料:
  • 这是我的建筑。格雷德尔: 我试图找出问题所在,使用以下代码来分析问题: 结果是:

  • 我在使用fs.readfile进行同步时遇到了一个问题,他们没有在第一次初始化,如果我再次尝试请求,那么我就有结果了。我知道我可以用promise和我从Kriskowal找到一些有用的东西。我试过但没有成功。我不太明白如何实施它。如果有人能帮忙,我将永远感激。 代码:

  • 我想从我的对象生成一个JSON字符串: 每次我尝试这样做,我得到这个错误: 这些是我的BomItem类的属性: 我引用的BomModule类的属性: 知道是什么导致了这个错误吗?我该如何修复它?

  • 事件处理程序添加到GameGui.java类的GridPane中,从第82行开始。 基本上,我试图找到您在网格窗格中拖动这个对象的任何节点的索引。通过将SetonMouseEnter应用到gridpane中的每个节点,我可以在不拖动的情况下完成这一任务,但是当我试图利用SetonMouseDragEnter时,我什么也没有得到。 有人有办法让这个工作吗? 这些是我应用于GridPane中节点的事件

  • 我知道我可以获得包名并从完整的类名中去掉相应数量的字符,但我猜已经有人这么做了?

  • 如何调用从公共静态空白到非静态的公共空白碎片类?或者有另一种方法在(listViewHolder.dot.setOnClickListener(new View.OnClickListener()和公共无效搜索3())