问题在于 Scala 枚举的字节码包含可能值的集合 - 每个值都是枚举的一个实例。
例如,如果我们运行javap CoinFaces
on:
object CoinFaces extends Enumeration {
type CoinFaces = Value
val Heads, Tails = Value
}
我们可以看到Java反汇编包含静态字段values
类型的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();
}
这意味着从 Java 开始,所有 Scala 枚举都包含循环引用。最简单的解决方案是将这些字段注释为@transient
(https://stackoverflow.com/a/14489534/323177)。不幸的是,因为我们无法注释为您的自定义 Scala 生成的字节码Enumeration
,解决方案是创建一个自定义 GSON 序列化器,手动将枚举值序列化为字符串。
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());
}
}
然后在构建过程中将其注册为类型适配器Gson
对象,然后这将序列化枚举值。
Gson gson = new GsonBuilder()
.registerTypeAdapter(Enumeration.Value.class, new GsonScalaEnumerationSerializer())
.create();