首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将泛型类型传递给Argonaut

如何将泛型类型传递给Argonaut
EN

Stack Overflow用户
提问于 2013-06-11 19:15:18
回答 2查看 1.9K关注 0票数 3

我正在尝试包装Argonaut (http://argonaut.io),以便在Scala项目中序列化/反序列化JSON。我们之前在使用Jerkson,但由于它已经停止使用,我们正在寻找替代方案。

这是基本的JSON包装器

代码语言:javascript
复制
import argonaut._, Argonaut._

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

当我尝试编译它时,我得到了以下错误。

代码语言:javascript
复制
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]
                  ^

任何关于如何解决这个问题的建议或关于我做错了什么的指示都将不胜感激。

另外,我们也非常欢迎关于替代JSON框架的建议。

我对Scala/Java以及泛型是如何工作的还是个新手,但我已经写.NET/C#很多年了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-11 20:08:51

为了使您的代码正常工作,您需要像这样重新定义Json对象:

代码语言:javascript
复制
object Json {
  def Parse[T](input: String)(implicit decode:DecodeJson[T]): Option[T] = {
    input.decodeOption[T]
  }
}

您遗漏的是隐式DecodeJson实例,decodeOption函数需要该实例来确定如何解码。您还需要将返回类型定义为Option[T],而不仅仅是T。这一切工作的完整示例如下所示:

代码语言:javascript
复制
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": "foo@test.com",
      "name": "foo bar"
    }"""

    val userOpt = Json.Parse[User](json)
    println(userOpt)
  }
}

至于其他Json框架,您可以查看以下内容:

Play Json

json4s

spray-json

Jackson Scala Module

票数 7
EN

Stack Overflow用户

发布于 2013-06-11 20:07:32

看起来,像几乎所有的scala序列化库一样,Argonaut使用类型类模式。这听起来很奇特,但实际上它只是意味着,在序列化/反序列化T类型的对象时,它需要您隐式地传递另一个对象的一个实例,该实例将部分或全部流程交付给该对象。具体地说,当您执行decodeOption[T]时,您需要在作用域中包含一个argonaut.DecodeJson[T]实例( decodeOption将在反序列化期间使用该实例)。

您应该做的只是要求将这个隐式值传递给Parse (然后它将自动传递给decodeOption

代码语言:javascript
复制
def Parse[T](input: String)(implicit decoder: argonaut.DecodeJson[T]): Option[T] = {
  input.decodeOption[T]
}

Scala甚至提供了一些语法糖来缩短声明(这称为“上下文绑定”):

代码语言:javascript
复制
def Parse[T:argonaut.DecodeJson](input: String): Option[T] = {
  input.decodeOption[T]
}

现在,当调用Parse时,您需要在作用域中引入隐式的argonaut.DecodeJson值,否则调用将无法编译。显然,Argonaut对象已经为许多标准类型定义了解码器,所以对于这些类型,您不需要做任何特殊的事情。对于其他类型(比如您的自定义类型),您必须定义解码器并导入它们。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17042763

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档