0

I have a JSON file that looks like this:

{
    "Animals": [
        [
            543,
            "Mammals",
            [
                1,
                "Cat",
                22,
                45,
                18
            ],
            [
                2,
                "Dog",
                45,
                13,
                27
            ]
        ]
    ]
}

This consists of one key - Animals - and the rest is a value expressed as a List of a List of an int, string, and list of polymorphic lists.

When attempting to parse my data structure, I used case classes as so:

sealed abstract class subTypes
case class typeOfAnimal(possSubType: String) extends subTypes
case class animalTraits(trait: Int) extends subTypes
case class animalResults(id: Int, type: String, results: List[List[subTypes]])
case class Animals(rows: List[List[animalResults]])

This fails. What is the easiest way to go about parsing such a complicated structure, deserializing from JSON to scala types.

What is the process to accomplish this?

Any tips are great.

Thanks!

nietsnegttiw
  • 371
  • 1
  • 5
  • 16
  • Can you not work from my answer on [your previous question](http://stackoverflow.com/questions/32993338/converting-very-complicated-json-objects-to-scala-objects-with-case-classes-in) ? – Peter Neyens Oct 15 '15 at 17:10
  • I think the polymorphic list factor makes it difficult to accomplish this. I had trouble reconciling the fact that lists contained strings and ints. Custom serialization only seemed to work in the case where lists were homogeneous. – nietsnegttiw Oct 15 '15 at 17:22

1 Answers1

2

We can create a CustomSerializer for SubType, so you can handle the polymorphic list. The rest should be similar to your previous question.

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
import org.json4s.native.Serialization

sealed trait SubType
case class TypeOfAnimal(possSubType: String) extends SubType
case class AnimalTrait(`trait`: Int) extends SubType

object SubTypeSerializer extends CustomSerializer[SubType](format => ( {
    case JString(subType) => TypeOfAnimal(subType)
    case JInt(animalTrait) => AnimalTrait(animalTrait.toInt)
  }, { 
    case TypeOfAnimal(st) => JString(st)
    case AnimalTrait(tr) => JInt(tr)
  }
))

Which you could use as :

implicit val formats = Serialization.formats(NoTypeHints) + SubTypeSerializer

val json = """[2, "Dog", 45, 13, 27]"""
parse(json).extract[List[SubType]]
// List[SubType] = List(
//   AnimalTrait(2), TypeOfAnimal(Dog), AnimalTrait(45), 
//   AnimalTrait(13), AnimalTrait(27)
// )
Community
  • 1
  • 1
Peter Neyens
  • 9,770
  • 27
  • 33
  • May I ask why SubType is defined as a sealed trait? When trying to compile this as it stands, I get a "No constructor for type SubType" error. Should this be an abstract class or an object of some kind instead? – nietsnegttiw Oct 19 '15 at 15:31
  • For traits vs abstract classes, see [this question](http://stackoverflow.com/questions/1991042/what-is-the-advantage-of-using-abstract-classes-instead-of-traits). I'm not sure why you are getting this error without the rest of your code. – Peter Neyens Oct 19 '15 at 16:10
  • The issue was conflicting import statements between json4s native json methods, and those of jackson json methods. Thanks again! – nietsnegttiw Oct 19 '15 at 16:49