2

The below codes causing StackOverflowError. purpose of the code is to create a json string from java class.

for (ControlTransaction crt : ctrList) {
                crt= new ControlTransaction();// for test, Still issue
                final Gson gson = new GsonBuilder().registerTypeAdapter(
                ControlTransaction.class,
                  new ControlTransactionSerializer()).create();
                String jsonControlTransactionString = gson.toJson(crt);
                strList.add(jsonControlTransactionString);

            }

My class looks like

public class ControlTransaction implements IsSerializable, Serializable ,IsBean{
    private long id;
    private String value; // H
    private String lastValue; // H
    private FormTransaction formTransaction;
    private List<FormTransaction> gridRows;
    private ControlTransaction referenceGridTransaction;
    private RowTransaction fkRowTransaction;
    private ReportTransaction reportTransaction;
    //getters ... setters
}

Stack trace followed like this, Let me know

Caused by: java.lang.StackOverflowError
at com.google.gson.stream.JsonWriter.<init>(JsonWriter.java:190)
at com.google.gson.internal.bind.JsonTreeWriter.<init>(JsonTreeWriter.java:58)
at com.google.gson.Gson.toJsonTree(Gson.java:478)
at com.google.gson.Gson$3.serialize(Gson.java:140)
at com.nextenders.common.ControlTransactionSerializer.serialize(ControlTransactionJsonUtil.java:129)
at com.nextenders.common.ControlTransactionSerializer.serialize(ControlTransactionJsonUtil.java:1)
at com.google.gson.TreeTypeAdapter.write(TreeTypeAdapter.java:70)
at com.google.gson.Gson.toJson(Gson.java:586)
at com.google.gson.Gson.toJsonTree(Gson.java:479)
at com.google.gson.Gson$3.serialize(Gson.java:140)
at com.nextenders.common.ControlTransactionSerializer.serialize(ControlTransactionJsonUtil.java:129)
at com.nextenders.common.ControlTransactionSerializer.serialize(ControlTransactionJsonUtil.java:1)
at com.google.gson.TreeTypeAdapter.write(TreeTypeAdapter.java:70)
at com.google.gson.Gson.toJson(Gson.java:586)
at com.google.gson.Gson.toJsonTree(Gson.java:479)
at com.google.gson.Gson$3.serialize(Gson.java:140)
at com.nextenders.common.ControlTransactionSerializer.serialize(ControlTransactionJsonUtil.java:129)
at com.nextenders.common.ControlTransactionSerializer.serialize(ControlTransactionJsonUtil.java:1)
at com.google.gson.TreeTypeAdapter.write(TreeTypeAdapter.java:70)
at com.google.gson.Gson.toJson(Gson.java:586)
at com.google.gson.Gson.toJsonTree(Gson.java:479)
at com.google.gson.Gson$3.serialize(Gson.java:140)

Here is my serializer and deserializer

class ControlTransactionDeserializer implements
        JsonDeserializer<ControlTransaction> {
    @Override
    public ControlTransaction deserialize(JsonElement json, Type type,
            JsonDeserializationContext context) throws JsonParseException {
        return context.deserialize(json, type);
    }
}

class ControlTransactionSerializer implements
        JsonSerializer<ControlTransaction> {

    @Override
    public JsonElement serialize(ControlTransaction ctr, Type type,
            JsonSerializationContext context) {
        return context.serialize(ctr, type);
    }
}

Whats going on in backend. I just passed a empty Object, that means new ControlTransaction(), Still unable to parse.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307

1 Answers1

5

The point of a JsonSerializer is to serialize the fields of an Object, not the object itself. However, you are passing the object you've already told Gson to serialize. The following

@Override
public JsonElement serialize(ControlTransaction ctr, Type type,
        JsonSerializationContext context) {
    return context.serialize(ctr, type);
}

is equivalent to

@Override
public JsonElement serialize(ControlTransaction ctr, Type type,
        JsonSerializationContext context) {
    return new GsonBuilder().registerTypeAdapter(
            ControlTransaction.class,
              new ControlTransactionSerializer()).create().toJsonTree(ctr);
}

which I hope you can see is going into recursive loop.

The JsonSerializationContext is basically the underlying structure that the Gson object uses to serialize your object. When it sees your type ControlTransaction, it will delegate to your custom JsonSerializer. But your JsonSerializer will send it back to the JsonSerializationContext and the loop goes on.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Thanks for looking in to the issue. What you suggest is won't compile. If possible please check the class `JsonDeserializer` http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/JsonDeserializer.html and an example also there. – Suresh Atta Jan 08 '14 at 05:57
  • @sᴜʀᴇsʜᴀᴛᴛᴀ I wasn't being careful (or trying to make it compile). It's just to give you an idea that the `JsonSerializationContext` is basically the underlying structure that the `Gson` object uses to serialize your object. When it sees your type `ControlTransaction`, it will delegate to your custom `JsonSerializer`. But your `JsonSerializer` will send it back to the `JsonSerializationContext` and the loop goes on. – Sotirios Delimanolis Jan 08 '14 at 05:59
  • @sᴜʀᴇsʜᴀᴛᴛᴀ [Here's](http://stackoverflow.com/questions/6050869/how-to-invoke-another-serializer-from-a-custom-gson-jsonserializer) an example of custom serialization. – Sotirios Delimanolis Jan 08 '14 at 06:01
  • 3
    @sᴜʀᴇsʜᴀᴛᴛᴀ Your start of day, my end of day :) You're welcome. Good morning! – Sotirios Delimanolis Jan 08 '14 at 06:08
  • 1
    Thanks Sotirios. Good night :) Your brains are still active even at end of the day. – Suresh Atta Jan 08 '14 at 06:09