Search code examples
scalajerkson

how to pass generic types to Argonaut


I am trying to wrap Argonaut (http://argonaut.io) in order to serialize/deserialize JSON in a Scala project. We where using Jerkson before but as it has been discontinued we are looking for an alternative.

This is the basic JSON wrapper

import argonaut._, Argonaut._

object Json {
  def Parse[T](input: String): T = {
    input.decodeOption[T].get
  }
}

When I try and compile this I get the following errors.

could not find implicit value for evidence parameter of type argonaut.DecodeJson[T]
    input.decodeOption[T]
                  ^
not enough arguments for method decodeOption: (implicit evidence$6: argonaut.DecodeJson[T]) Option[T].
Unspecified value parameter evidence$6.
    input.decodeOption[T]
                  ^

Any suggestions on how to fix this or pointers on what I am doing wrong would be most appreciated.

Also suggestions on alternative JSON frameworks are very welcome.

I'm kind of new to Scala/Java and how generics work there but I have been writing .NET/C# for many years.


Solution

  • In order to make your code work, you will need to redefine the Json object like so:

    object Json {
      def Parse[T](input: String)(implicit decode:DecodeJson[T]): Option[T] = {
        input.decodeOption[T]
      }
    }
    

    The thing you were missing was the implicit DecodeJson instance that the decodeOption function needs in order to figure out how to decode. You also need to define the return type as Option[T] instead of just T. A full example of this all working would look like this:

    import argonaut._, Argonaut._
    case class User(id:Long, email:String, name:String)
    
    object Json {
      def Parse[T](input: String)(implicit decode:DecodeJson[T]): Option[T] = {
        input.decodeOption[T]
      }
    }
    
    object JsonTest{
      implicit val userDecode = casecodec3(User.apply, User.unapply)("id", "email", "name")
    
      def main(args: Array[String]) {
        val json = """{
          "id": 1,
          "email": "[email protected]",
          "name": "foo bar"
        }"""
    
        val userOpt = Json.Parse[User](json)
        println(userOpt)
      }
    }
    

    As far as other Json frameworks, you could look into:

    Play Json

    json4s

    spray-json

    Jackson Scala Module