java Gson.toJson 给出了 StackOverFlowError,在这种情况下如何获得正确的 json?(公共静态类)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13460200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Gson.toJson gives StackOverFlowError, how to get proper json in this case? (public static class)
提问by Jeroen
I currently have the following class:
我目前有以下课程:
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;
}
}
of which I would like to create json out of. In order to do this, I am using the following code:
我想从中创建json。为了做到这一点,我使用了以下代码:
Gson gson= new Gson();
Type hmType= new TypeToken<TabInfo>(){}.getType();
String json = gson.toJson(methodToGetAnInstanceOfTabInfoClassHere, hmType);
When I am doing this, I get a java.lang.StackOverFlowError:
当我这样做时,我得到一个 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.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.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.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.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.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.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.write(ReflectiveTypeAdapterFactory.java:89)
E/AndroidRuntime(20692): at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
So, my question is: how can I get my gson to create valid json of the java objects from class TabInfo without getting a stackoverflowerror?
所以,我的问题是:如何让我的 gson 从 TabInfo 类创建 Java 对象的有效 json 而不会出现 stackoverflowerror?
Btw. as all of you can see, I have not asked that many questions before, so if you have any feedback for me on how to improve my question: let me know!
顺便提一句。正如你们所看到的,我以前没有问过那么多问题,所以如果你们对我的问题有任何反馈,请告诉我如何改进我的问题:让我知道!
EDIT 1:The bundle class is a standard bundle, fi: Bundle args = new Bundle(); args.putint("someint", 1);
编辑 1:bundle 类是一个标准的 bundle,fi: Bundle args = new Bundle(); args.putint("someint", 1);
See the updated stacktrace...
查看更新的堆栈跟踪...
EDIT 2:If I take a single instance of a TabInfo, by using a String.class as an argument, eg:
编辑 2:如果我采用 TabInfo 的单个实例,通过使用 String.class 作为参数,例如:
TabInfo test= new TabInfo("test", String.class, new Bundle());
String result=gson.toJson(test, hmType);
Then I get the following stacktrace:
然后我得到以下堆栈跟踪:
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.write(TypeAdapters.java:64)
E/AndroidRuntime(22068): at com.google.gson.internal.bind.TypeAdapters.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.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)
Does this mean that I need to make a TypeToken for all 24 different classes that might be part of a TabInfo class? How do I resolve this?
这是否意味着我需要为可能属于 TabInfo 类的所有 24 个不同类创建一个 TypeToken?我该如何解决?
Edit 3
编辑 3
Ok, thanks to @Zaske, I have found a fix for the first part of my problem. Using another class signature as shown below
好的,感谢@Zaske,我找到了解决问题第一部分的方法。使用另一个类签名,如下所示
static final class TabInfo{
TabInfo(String _tag, String _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
Now I can make json out of it, but, when I try to do this by creating the actual HashMap < String, < Stack < TabInfo > > > then again I run into trouble. The typetoken i use in that case is:
现在我可以用它来制作 json,但是,当我尝试通过创建实际的 HashMap < String, < Stack < TabInfo > > > 来做到这一点时,我又遇到了麻烦。我在这种情况下使用的 typetoken 是:
Type hmType = new TypeToken<HashMap<String, Stack<TabInfo>>>(){}.getType();
So, now my final question is: how can I convert a set of tabinfo-stacks in a hashmap to json?
所以,现在我的最后一个问题是:如何将哈希图中的一组 tabinfo 堆栈转换为 json?
Edit 4Here's some more information: The used Bundle class is the Bundle class used in Android to provide arguments to activities and fragments. (See http://developer.android.com/reference/android/os/Bundle.html)
编辑 4这里有更多信息:使用的 Bundle 类是 Android 中用于为活动和片段提供参数的 Bundle 类。(见http://developer.android.com/reference/android/os/Bundle.html)
If I do
如果我做
TabInfo test= new TabInfo("test", "String", new Bundle());
//stage 1 test
String result=gson.toJson(test);
Log.d("new result=",result);
Then I do get my Json output (see below)
然后我得到了我的 Json 输出(见下文)
D/new result=(20816): {"args":{"mClassLoader":{"packages":{}},"mMap":{},"mHasFds":false,"mFdsKnown":true,"mAllowFds":true},"clss":"String","tag":"test"}
However, when I try to make a Hashmap of stacks out of the TabInfo classes, then it breaks (it runs out of memory...)...
但是,当我尝试从 TabInfo 类中创建堆栈的 Hashmap 时,它会中断(内存不足......)...
采纳答案by Yair Zaslavsky
As I suggested the "change from class" to string,
I allow myself for the sake of our readers to answer here for the first part:
Don't use Class as a field, but use String that will contain the full class name
TabInfo should look like:
当我建议“从类更改”为字符串时,
为了我们的读者,我允许自己在第一部分回答:
不要使用类作为字段,而是使用包含完整类名
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;
}
}
Regarding 2nd part:
I don't know what Bundle class is - please provide info,
as I had to change a bit and write my own class for experiment.
关于第二部分:
我不知道 Bundle 类是什么 - 请提供信息,
因为我不得不进行一些更改并编写自己的类进行实验。
Person class is:
人类是:
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;
}
Main class for checking is:
检查的主要类是:
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);
}
}
Feel free to run it, you will see both str and str2 are printed just fine.
随意运行它,你会看到 str 和 str2 都打印得很好。
Update
I checked the Bundle class, and saw that it contains too much information (In my humble opinion) to be a simple arguments collection.
I don't see why in the above question a simple collection cannot be used instead.
Serialization should contain as minimal data as possible
(think about cases in which you take a serialized data and store it on some storage device, or send it over the network).
So unless Bundle provides you a special functionality that a collection doesn't - don't use it.
As a rule of thumb remember you cannot serialize everything with Json - there are limitations (recursive data-types for example) - so yes, there will be cases where you will have to translate from one type to a JSON-serializable type.
This pattern is also used in other cases, I suggest you read more about data transfer objects
更新
我检查了 Bundle 类,发现它包含太多信息(以我的拙见)作为一个简单的参数集合。
我不明白为什么在上面的问题中不能使用简单的集合。
序列化应包含尽可能少的数据
(考虑将序列化数据存储在某个存储设备上或通过网络发送的情况)。因此,除非 Bundle 为您提供了集合没有的特殊功能 - 不要使用它。
根据经验,您不能使用 Json 序列化所有内容 - 存在限制(例如递归数据类型) - 所以是的,在某些情况下,您必须从一种类型转换为 JSON 可序列化类型。
这种模式也用于其他情况,建议您阅读更多有关数据传输对象的信息