Search code examples
scalagsonto-json

Converting a nested List in using Gson.tojson


I'm using Scala, but this applies to Java as well - it appears Gson is having issues converting a List nested within a case class/within another object:

case class Candy(name:String, price:Double)
case class PersonCandy(name:String, age:Int, candyList:List[Candy])

val candies = List(Candy("M&M's", 1.99), Candy("Snickers", 1.59), Candy("Butterfinger", 2.33))
val personC = PersonCandy("Mark", 19, candies)

val pollAsJson = new Gson().toJson(personC)

The REPL shows the resulting pollAsJson as follows:

pollAsJson: String = {"name":"Mark","age":19,"candyList":{}}

My workaround could be to convert the nested candyList, convert the personC and then since both are just Strings, manually hack them toether, but this is less than ideal. Reading blogs and usages and the like seems that Gson can extract and convert nested inner classes just fine, but when a Collection is the nested class, it seems to have issues. Any idea?


Solution

  • The problem is not related with case classes or nesting, but rather with Scala collection types which are not supported properly in Gson.

    To prove that, let's change PersonCandy to

    case class PersonCandy(name:String, age:Int, candyList: java.util.List[Candy])
    

    And convert candies to a Java List:

    import scala.collection.JavaConverters._
    val candies = List(/* same items */).asJava
    

    And the JSON is OK:

    {"name":"Mark","age":19,"candyList":[{"name":"M\u0026M\u0027s","price":1.99},{"name":"Snickers","price":1.59},{"name":"Butterfinger","price":2.33}]}
    

    And if you try to produce a JSON for the original candies list, it will produce:

    {"head":{"name":"M\u0026M\u0027s","price":1.99},"tl":{}}
    

    Which reflects the head :: tail structure of the list.

    Gson is a lib primarily used with Java code.

    For Scala, there is a variety of choices. I'd suggest to try some from the answers to this question.