xmlscalasprayspray-client

How to unmarshall a list of case class in Spray


First time Spray user failing to find any proper examples on this anywhere. I'm looking to unmarshall the XML API response that contains a List[Person].

Say case class Person(name: String, age: Int). The unmarshaller should produce the appropriate List[Person].

Spray has a default NodeSeqUnmarshaller but I can't figure out how to chain things properly, would be grateful for any pointers.


Solution

  • I had to solve this problem in my application. Here is some code based on your example case class that you might find to be helpful.

    My approach uses Unmarshaller.delegate as discussed here.

    import scala.xml.Node
    import scala.xml.NodeSeq
    import spray.httpx.unmarshalling._
    import spray.httpx.unmarshalling.Unmarshaller._
    
    case class Person(name: String, age: Int)
    
    object Person {
      def fromXml(node: Node): Person = {
        // add code here to instantiate a Person from a Node
      }
    }
    
    case class PersonSeq(persons: Seq[Person])
    
    object PersonSeq {
      implicit val PersonSeqUnmarshaller: Unmarshaller[PersonSeq] = Unmarshaller.delegate[NodeSeq, PersonSeq](MediaTypes.`text/xml`, MediaTypes.`application/xml`) {
        // Obviously, you'll need to change this function, but it should
        // give you an idea of how to proceed.
        nodeSeq =>
          val persons: NodeSeq = nodeSeq \ "PersonList" \ "Person"
          PersonSeq(persons.map(node => Person.fromXml(node))
      }
    }