2

Hello I would like to transform json object into map using implicit Reads. With the code below I run into a StackOverflow error, any one could see what the problem is :

"pass": {
  "key-1": {
    "field1": "aaaa",
    "field2": "aaaa"
  },
  "key-2": {
    "field1": "aaaa",
    "field2": "aaaa"
  },
  "key-3": {
    "field1": "aaaa",
    "field2": "aaaa"
  }
}

case class Pass(field1: String, field2: String)

implicit val mapReads: Reads[Map[String, Pass]] = new Reads[Map[String, Pass]] {
  def reads(jv: JsValue): JsResult[Map[String, Pass]] =
    JsSuccess(jv.as[Map[String, Pass]].map{
      case (k, v) => k -> v.asInstanceOf[Pass]
    })
}

val passMap = (json \ "pass").validate[Map[String, Pass]]

Here is the stack error :

java.lang.StackOverflowError
  at play.api.libs.json.JsReadable$class.as(JsReadable.scala:23)
  at play.api.libs.json.JsObject.as(JsValue.scala:124)
  at com.MyHelper$$anon$1.reads(MyHelper.scala:51)
  at play.api.libs.json.Format$$anon$3.reads(Format.scala:65)
  at play.api.libs.json.JsValue$class.validate(JsValue.scala:17)
  at play.api.libs.json.JsObject.validate(JsValue.scala:124)
  at play.api.libs.json.JsReadable$class.as(JsReadable.scala:23)
  at play.api.libs.json.JsObject.as(JsValue.scala:124)
amritanshu
  • 777
  • 13
  • 25
jerome
  • 2,029
  • 4
  • 38
  • 58

1 Answers1

1

Maybe you will be more likely to create a MapPass class case and use Json.format to do the work for you!

import play.api.libs.json._

val a: String = """{
  "pass": {
    "key-1": {
    "field1": "aaaa",
    "field2": "aaaa"
  },
    "key-2": {
    "field1": "aaaa",
    "field2": "aaaa"
  },
    "key-3": {
    "field1": "aaaa",
    "field2": "aaaa"
  }
  }
}"""

case class Pass(field1: String, field2: String)

case class MapPass(pass: Map[String, Pass])

implicit val passFormat: Format[Pass] = Json.format[Pass]
implicit val mapPassFormat: Format[MapPass] = Json.format[MapPass]

val json = Json.parse(a)
val mapPassJsResult = json.validate[MapPass]
val mapPass = mapPassJsResult.get
print(mapPass.pass.mkString("\n"))

It worked like that for me:

enter image description here

Rodo
  • 312
  • 4
  • 12
  • I tried your code and got the error `JsError(List((/pass,List(JsonValidationError(List(error.path.missing),WrappedArray())))))` – jerome Mar 29 '18 at 06:18
  • In my exemple I simplified the json, but the real json is bigger and I have to extract pass using `(json \ "pass").validate[MapPass]` – jerome Mar 29 '18 at 06:23
  • Can not be that I gave you an error I insert a scalaworksheet with the preview of the example ... with any size, you can use the json.format macro, as long as it is a case class and it does not pass 22 fields, cheers – Rodo Mar 29 '18 at 07:03