Reputation: 2624
I'm trying to use Gson and Scala in a simple test. This is working fine when printing the author instance, where I'm receiving a json representation of the author. However, when replacing it with the book instance, I'm getting a StackOverflowError. I read in other places that this might happen if there is a circular reference between the classes, but I can't see it here. I'm attaching the code and part of the error stack below and am thankful for any suggestions as to how to solve this problem.
Code:
import com.google.gson._
import java.lang.reflect.Type
import scala.collection.mutable._
object GsonTest extends App {
val gsonBuilder = new GsonBuilder
gsonBuilder.registerTypeAdapter(classOf[Author], new AuthorSerializer)
gsonBuilder.registerTypeAdapter(classOf[Book], new BookSerializer)
val book = Book("test book")
val author = Author("test author")
book.authors += author
val gson = new Gson
println(gson.toJson(author))
println(gson.toJson(book))
}
case class Author(name: String)
case class Book(name: String) {
val authors = MutableList[Author]()
}
class AuthorSerializer extends JsonSerializer[Author] {
override def serialize(src: Author, typeOfSrc: Type, context: JsonSerializationContext) = {
val json = new JsonObject
json.addProperty("name", src.name)
json
}
}
class BookSerializer extends JsonSerializer[Book] {
override def serialize(src: Book, typeOfSrc: Type, context: JsonSerializationContext) = {
val json = new JsonObject
json.addProperty("name", src.name)
val jsonAuthorArray = new JsonArray
for (author <- src.authors) {
jsonAuthorArray.add(context.serialize(author))
}
json.add("authors", jsonAuthorArray)
json
}
}
Error stack:
Exception in thread "main" java.lang.StackOverflowError
at com.google.gson.reflect.TypeToken.equals(TypeToken.java:284)
at java.util.HashMap.getNode(HashMap.java:578)
at java.util.HashMap.get(HashMap.java:556)
at java.util.Collections$SynchronizedMap.get(Collections.java:2644)
at com.google.gson.Gson.getAdapter(Gson.java:332)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:55)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
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:195)
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:195)
...and so on
Upvotes: 0
Views: 1954
Reputation: 1493
You are missing gsonBuilder.create()
, so type adapters donsn't registered properly:
val gsonBuilder = new GsonBuilder
gsonBuilder.registerTypeAdapter(classOf[Author], new AuthorSerializer)
gsonBuilder.registerTypeAdapter(classOf[Book], new BookSerializer)
val book = Book("test book")
val author = Author("test author")
book.authors += author
val gson = gsonBuilder.create() // this line !!!
println(gson.toJson(author))
println(gson.toJson(book))
Upvotes: 3