gson.toJson ()에서 StackOverflowError가 발생합니다.
내 개체에서 JSON 문자열을 생성하고 싶습니다.
Gson gson = new Gson();
String json = gson.toJson(item);
이 작업을 시도 할 때마다 다음 오류가 발생합니다.
14:46:40,236 ERROR [[BomItemToJSON]] Servlet.service() for servlet BomItemToJSON threw exception
java.lang.StackOverflowError
at com.google.gson.stream.JsonWriter.string(JsonWriter.java:473)
at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:347)
at com.google.gson.stream.JsonWriter.value(JsonWriter.java:440)
at com.google.gson.internal.bind.TypeAdapters$7.write(TypeAdapters.java:235)
at com.google.gson.internal.bind.TypeAdapters$7.write(TypeAdapters.java:220)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:200)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:843)
다음은 내 BomItem 클래스 의 속성입니다 .
private int itemId;
private Collection<BomModule> modules;
private boolean deprecated;
private String partNumber;
private String description; //LOB
private int quantity;
private String unitPriceDollar;
private String unitPriceEuro;
private String discount;
private String totalDollar;
private String totalEuro;
private String itemClass;
private String itemType;
private String vendor;
private Calendar listPriceDate;
private String unitWeight;
private String unitAveragePower;
private String unitMaxHeatDissipation;
private String unitRackSpace;
참조 된 BomModule 클래스의 속성 :
private int moduleId;
private String moduleName;
private boolean isRootModule;
private Collection<BomModule> parentModules;
private Collection<BomModule> subModules;
private Collection<BomItem> items;
private int quantity;
이 오류의 원인은 무엇입니까? 어떻게 고칠 수 있습니까?
그 문제는 순환 참조가 있다는 것입니다.
에서 BomModule
클래스는하기 참조하고 :
private Collection<BomModule> parentModules;
private Collection<BomModule> subModules;
에 대한 자체 참조는 BomModule
분명히 GSON이 전혀 좋아하지 않습니다.
해결 방법은 null
재귀 루프를 방지하기 위해 모듈을 로 설정하는 것 입니다. 이렇게하면 StackOverFlow-Exception을 피할 수 있습니다.
item.setModules(null);
또는 키워드 를 사용하여 직렬화 된 json에 표시 하지 않으려 는 필드를 표시하십시오 transient
. 예 :
private transient Collection<BomModule> parentModules;
private transient Collection<BomModule> subModules;
Log4J 로거를 클래스 속성으로 사용할 때 다음과 같은 문제가 발생했습니다.
private Logger logger = Logger.getLogger(Foo.class);
이것은 로거를 만들 static
거나 단순히 실제 기능으로 이동 하여 해결할 수 있습니다 .
Realm을 사용 중이고이 오류가 발생하고 문제를 일으키는 객체가 RealmObject를 확장 realm.copyFromRealm(myObject)
하는 경우 직렬화를 위해 GSON으로 전달하기 전에 모든 Realm 바인딩없이 복사본을 만드는 것을 잊지 마십시오 .
복사되는 객체 중 하나에 대해서만 이것을 놓쳤습니다. 스택 추적이 객체 클래스 / 유형의 이름을 지정하지 않기 때문에 깨달았습니다. 문제는 순환 참조로 인해 발생하지만 RealmObject 기본 클래스의 어딘가에 순환 참조이므로 자신의 하위 클래스가 아니므로 발견하기가 더 어렵습니다!
As SLaks said StackOverflowError happen if you have circular reference in your object.
To fix it you could use TypeAdapter for your object.
For example, if you need only generate String from your object you could use adapter like this:
class MyTypeAdapter<T> extends TypeAdapter<T> {
public T read(JsonReader reader) throws IOException {
return null;
}
public void write(JsonWriter writer, T obj) throws IOException {
if (obj == null) {
writer.nullValue();
return;
}
writer.value(obj.toString());
}
}
and register it like this:
Gson gson = new GsonBuilder()
.registerTypeAdapter(BomItem.class, new MyTypeAdapter<BomItem>())
.create();
or like this, if you have interface and want to use adapter for all its subclasses:
Gson gson = new GsonBuilder()
.registerTypeHierarchyAdapter(BomItemInterface.class, new MyTypeAdapter<BomItemInterface>())
.create();
My answer is a little bit late, but I think this question doesn't have a good solution yet. I found it originally here.
With Gson you can mark the fields you do want to be included in json with @Expose
like this:
@Expose
String myString; // will be serialized as myString
and create the gson object with:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Circular references you just do not expose. That did the trick for me!
This error is common when you have a logger in your super class. As @Zar suggested before, you can use static for your logger field, but this also works:
protected final transient Logger logger = Logger.getLogger(this.getClass());
P.S. probably it will work and with @Expose annotation check more about this here: https://stackoverflow.com/a/7811253/1766166
I have the same problem. In my case the reason was that constructor of my serialized class take context variable, like this:
public MetaInfo(Context context)
When I delete this argument, error has gone.
public MetaInfo()
Edit: Sorry for my bad, this is my first answer. Thanks for your advises.
I create my own Json Converter
The main solution I used is to create a parents object set for each object reference. If a sub-reference points to existed parent object, it will discard. Then I combine with an extra solution, limiting the reference time to avoid infinitive loop in bi-directional relationship between entities.
My description is not too good, hope it helps you guys.
This is my first contribution to Java community (solution to your problem). You can check it out ;) There is a README.md file https://github.com/trannamtrung1st/TSON
In Android, gson stack overflow turned out to be the declaration of a Handler. Moved it to a class that isn't being deserialized.
Based on Zar's recommendation, I made the the handler static when this happened in another section of code. Making the handler static worked as well.
BomItem
refers to BOMModule
(Collection<BomModule> modules
), and BOMModule
refers to BOMItem
(Collection<BomItem> items
). Gson library doesn't like circular references. Remove this circular dependency from your class. I too had faced same issue in the past with gson lib.
I had this problem occur for me when I put:
Logger logger = Logger.getLogger( this.getClass().getName() );
in my object...which made perfect sense after an hour or so of debugging!
For Android users, you cannot serialize a Bundle
due to a self-reference to Bundle
causing a StackOverflowError
.
To serialize a bundle, register a BundleTypeAdapterFactory
.
Avoid unnecessary workarounds, like setting values to null or making fields transient. The right way to do this, is to annotate one of the fields with @Expose and then tell Gson to serialize only the fields with the annotation:
private Collection<BomModule> parentModules;
@Expose
private Collection<BomModule> subModules;
...
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
I had a similar issue where the class had an InputStream variable which I didn't really have to persist. Hence changing it to Transient solved the issue.
참고URL : https://stackoverflow.com/questions/10209959/gson-tojson-throws-stackoverflowerror
'IT박스' 카테고리의 다른 글
오래 실행되는 PHP 스크립트를 관리하는 가장 좋은 방법은 무엇입니까? (0) | 2020.10.19 |
---|---|
Web.Config 디버그 / 릴리스 (0) | 2020.10.19 |
0과 비교할 때 int 연산자! = 및 == (0) | 2020.10.19 |
부트 스트랩에서 두 열 사이의 세로 구분선 (0) | 2020.10.19 |
Mongoose-exec 함수는 무엇을합니까? (0) | 2020.10.19 |