Home > front end >  Parsing a n Option[List[Object]] using SprayJson Scala
Parsing a n Option[List[Object]] using SprayJson Scala

Time:11-29

running into some Json quirks. I am writing serialize-deserialize logic for an incoming request which contains an object in form of JSON which is IndividualObject. I am using Spray Json for this. Tried using toVector, mapping list of items to resolve the following but not able to resolve the type mismatch.

case class IndividualObject(id: String, path: String)
object IndividualObjectJson extends DefaultJsonProtocol {
    implicit val individualObjectFormat = jsonFormat2(IndividualObject.apply)
}

case class IncomingRequest(anotherId: String, indivObjects: Option[List[IndividualObject]])
trait IncomingRequestJson extends SprayJsonSupport with DefaultJsonProtocol {
    implici val incomingRequestFormat: RootJsonFormat[IncomingRequest] = new RootJsonFormat[IncomingRequest] {
        override def read(json: JsValue): IncomingRequest = {
            val fields = json.asJsObject.fields
            IncomingRequest(
                anotherId = fields("anotherId").convertTo[String]
                indivObjects = fields("indivObjects").convertTo[Option[List[IndividualObject]]]
            )
         override def write(obj: IncomingRequest): JsValue = {
             val jsBuilder = Map.newBuilder[String,JsValue]
             jsBuilder  = "anotherId" -> JsString(obj.anotherId)
             jsBuilder  = "indivObjects" -> JsArray(obj.indivObjects.get map (IndividualObjectJson.individualObjectFormat))
             JsObject(jsBuilder.result())
         }

Found the following error in JsArray line: jsBuilder = "indivObjects" -> JsArray(obj.indivObjects.get map (IndividualObjectJson.individualObjectFormat))

Error: type mismatch
    found: spray.json.RootJsonFormat[IndividualObject]
    required: List[IndividualObject]
  

Any help is appreciated to understand why its not able to resolve Option[List[....]] for deserialization. Thanks

CodePudding user response:

You can use the jsonFormat2 to create default json readers/writers for case classes with two parameters. The compiler will inject the code via implicit resolution for handling these. But this is not a JsValue(JsString, JsObject, ....). If you create your own Json encoder/encoder you must include JsValue instances manually to create the final JsValue. Something like that:

  override def write(obj: IncomingRequest): JsValue = {
    val jsBuilder = Map.newBuilder[String, JsValue]
    jsBuilder  = "anotherId" -> JsString(obj.anotherId)
    jsBuilder  = "indivObjects" -> JsArray({
    obj.indivObjects match {
        case Some(list) =>
          list
            .map(el =>
              JsObject(
                Map("id" -> JsString(el.id), "path" -> JsString(el.path))
              )
            )
            .toVector
        case None => Vector.empty
      }
    })
    JsObject(jsBuilder.result())
  }

Something like that should compile.

  • Related