简体   繁体   中英

Gson:java.lang.StackOverflowError: null

i have a class Delete which i want to convert it into json using Gson library but when i convert it it throws exception of java.lang.StackOverflowError: null here is my class

import models.UserNotifications.MailMessages.DeleteReason._
import models.UserNotifications.MailMessages.DeleteStatus._

@SerialVersionUID(1)
class Delete extends Serializable {

  var deleteStatus : DeleteStatus = DELETED
  var deleteReason : DeleteReason = EXPIRED

  /*
   * Setters
   */

  def setDeleteStatus(deletestatus : String)= {
    deleteStatus = DeleteStatus.withName(deletestatus)
  } 
  def setDeleteReason ( deletereason : String) ={
    deleteReason = DeleteReason.withName(deletereason)
  }

  /*
   * Getter
   */

  def getDeleteStatus : DeleteStatus = {
    deleteStatus
  }
  def getDeleteReason : DeleteReason = {
    deleteReason
  }


}

here is enumeration classes DeleteStatus.scala

object DeleteStatus extends Enumeration {

  type DeleteStatus = Value
  val DELETED, ACTIVE = Value

}

DeleteReason.scala

object DeleteReason extends Enumeration{
  type DeleteReason = Value
  val EXPIRED , MANUALLY_DELETED = Value
}

Here is how i am converting in Json

var delete = new Delete

    val gson = new Gson();
    val g=gson.toJson(delete)

but it throws following exception

java.lang.StackOverflowError: null
    at com.google.gson.reflect.TypeToken.equals(TypeToken.java:284) ~[gson-2.3.1.jar:na]
    at java.util.HashMap.getNode(HashMap.java:571) ~[na:1.8.0_45]
    at java.util.HashMap.get(HashMap.java:556) ~[na:1.8.0_45]
    at java.util.Collections$SynchronizedMap.get(Collections.java:2584) ~[na:1.8.0_45]
    at com.google.gson.Gson.getAdapter(Gson.java:335) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:55) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:99) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:219) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:99) ~[gson-2.3.1.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:219) ~[gson-2.3.1.jar:na]

please help what is wrong in it

The issue is that the bytecode of a Scala Enumeration contains a collection of the possible values - each of which is an instance of the enumeration.

For example, if we run javap CoinFaces on:

object CoinFaces extends Enumeration {
  type CoinFaces = Value
  val Heads, Tails = Value
}

we can see that the Java disassembly contains static field values of type Enumeration$Value :

public final class CoinFaces {
  public static scala.Enumeration$Value Tails();
  public static scala.Enumeration$Value Heads();
  public static scala.Enumeration$ValueSet$ ValueSet();
  public static scala.Enumeration$ValueOrdering$ ValueOrdering();
  public static scala.Enumeration$Value withName(java.lang.String);
  public static scala.Enumeration$Value apply(int);
  public static int maxId();
  public static scala.Enumeration$ValueSet values();
  public static java.lang.String toString();
}

This means that from Java, all Scala enumerations contains cyclical references. The easiest solution to this is to annotate such fields as @transient ( https://stackoverflow.com/a/14489534/323177 ). Unfortunately, since we cannot annotate the generated bytecode for your custom Scala Enumeration , the solution is to create a custom GSON serializer that manually serializes the enumeration value as a String.

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import scala.Enumeration;

import java.lang.reflect.Type;

// Scala enumerations are static Java classes with values of type `Enumeration.Value`
public class GsonScalaEnumerationSerializer implements JsonSerializer<Enumeration.Value> {
  @Override
  public JsonElement serialize(final Enumeration.Value enumValue,
                               final Type typeOfEnum,
                               final JsonSerializationContext context) {

    return new JsonPrimitive(enumValue.toString());
  }
}

Then register this as a type adapter during construction of your Gson object and this will then serialise the Enumeration value.

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Enumeration.Value.class, new GsonScalaEnumerationSerializer())
    .create();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM