uzilan
uzilan

Reputation: 2624

StackOverflowError when using JsonSerializer with Gson and Scala

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

Answers (1)

aim
aim

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

Related Questions