scalagenerics

Scala Dynamic Parse Json using case class No Manifest available for T


I have a JSON string and I created a function which parses this JSON as an object using Scala case class. I wrote the below code to parse it in a generic way. However, It gave me an error:

def getJsonObj[T](jsonString:String): T = {
    implicit val formats: DefaultFormats.type = DefaultFormats
      parse(jsonString).extract[T]
}

Error can be found below:

Error:(19, 32) No Manifest available for T. 
parse(jsonString).extract[T] Error:(19, 32) not enough arguments for 
method extract: (implicit formats: org.json4s.Formats, implicit mf: 
scala.reflect.Manifest[T])T. Unspecified value parameter mf.
parse(jsonString).extract[T]

I found this No Manifest available for Type But I don't know how to fix it in my code. Also, I found this,Spark Scala - How to construct Scala Map from nested JSON (Scala: "No manifest available for type T") But I need to pass the case class to the function in a generic way. It seems a common problem but I can't solve it using the available answers as I am new in Scala.

Another point, How can I add try-catch to see if it's correctly parsed or not?


Solution

  • I think this answer solves your question, Scala: “No manifest available for type T”. It easily solved by implicitly passing on the manifest for the type method. I add an example of the code and a simple function for error handling.

      val jsonStr: String = """{"airports":[{"name":"sfo","score":1},{"name":"phx","score":1},{"name":"sjc","score":1}]}"""
    
      case class AirPortScores(name: String, score: Double)
      case class JsonRulesHandler(airports: List[AirPortScores])
    
      val json: JsonRulesHandler = getJsonObj[JsonRulesHandler](jsonStr)
      println(json)
    
    
      def getJsonObj[T](jsonString:String)(implicit m: Manifest[T]): T = {
        extractFrom(jsonString) match {
          case Success(jsonParsed) ⇒
            jsonParsed
          case Failure(exc) ⇒
            throw new IllegalArgumentException(exc)
        }
      }
    
      private def extractFrom[T](jsonString:String)(implicit m: Manifest[T]): Try[T] = {
        implicit val formats: DefaultFormats.type = DefaultFormats
    
        Try {
          parse(jsonString).extract[T]
        }
      }