【问题标题】:JSON to case class with generics decoding with json4sJSON to case class 使用 json4s 进行泛型解码
【发布时间】:2018-07-02 04:28:39
【问题描述】:

我正在尝试使用 json4s 构建一个 json 到 case class en/decoder 使用泛型 icw Manifest 似乎适用于普通类型/类,但更复杂的配置似乎会失败。

如何结合使用 json4s 从 json 字符串中提取更复杂的类型?

import org.json4s._
import org.json4s.native.JsonMethods._
implicit val formats = org.json4s.DefaultFormats

case class User(name:String)
case class Product(id:String)


case class Meta(count:Int)
case class ResultList[T: Manifest](meta: Meta, result: List[T])


// Without generics
case class ResultListUser(meta: Meta, result: List[User])
case class ResultListProduct(meta: Meta, result: List[Product])


// general decode method
def decode[T: Manifest](jsonStr: String): T = {
  parse(jsonStr).extract[T]
}


// data
val userJson = """{"meta":{"count":2},"result":[{"name":"Tom"},{"name":"Lucas"}]}"""
val productJson = """{"meta":{"count":2},"result":[{"id":"123"},{"id":"456"}]}"""


val resultListUser = decode[ResultListUser](userJson)

resultListUser:ResultListUser = ResultListUser(Meta(2),List(User(Tom), User(Lucas)))

val resultListProduct = decode[ResultListProduct](productJson)

resultListProduct: ResultListProduct = ResultListProduct(Meta(2),List(Product(123), Product(456)))

val resultListUser2 = decode[ResultList[User]](userJson)

org.json4s.package$MappingException:evidence$1 没有可用值

Manifest[User]、JNothing 类型没有构造函数

...

val resultListProduct2 = decode[ResultList[Product]](productJson)

org.json4s.package$MappingException:没有可用的证据价值$1 否 Manifest[Product] 类型的构造函数,JNothing 在 org.json4s.reflect.package$.fail(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:91) 在 org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:522) 在 org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:542) 在 org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:542) 在 scala.collection.TraversableLike$$anonfun$map$1.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230) 在 scala.collection.TraversableLike$$anonfun$map$1.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230) 在 scala.collection.mutable.ResizableArray$class.foreach(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:55) 在 scala.collection.mutable.ArrayBuffer.foreach(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:44) 在 scala.collection.TraversableLike$class.map(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230) 在 scala.collection.AbstractTraversable.map(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:100) 在 org.json4s.Extraction$ClassInstanceBuilder.instantiate(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:542) 在 org.json4s.Extraction$ClassInstanceBuilder.result(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:593) 在 org.json4s.Extraction$$anonfun$extract$6.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:396) 在 org.json4s.Extraction$$anonfun$extract$6.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:388) 在 org.json4s.Extraction$.customOrElse(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:602) 在 org.json4s.Extraction$.extract(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:388) 在 worksheet.worksheet(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:35)

原因:org.json4s.package$MappingException: No constructor for 类型 Manifest[Product], JNothing at org.json4s.reflect.package$.fail(package.scala:95) 在 org.json4s.Extraction$ClassInstanceBuilder$$anonfun$org$json4s$Extraction$ClassInstanceBuilder$$constructor$1.apply(Extraction.scala:477) 在 org.json4s.Extraction$ClassInstanceBuilder$$anonfun$org$json4s$Extraction$ClassInstanceBuilder$$constructor$1.apply(Extraction.scala:477) 在 scala.Option.getOrElse(Option.scala:121) 在 org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$constructor(Extraction.scala:477) 在 org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:532) 在 org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597) 在 org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:400) 在 org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:392) 在 org.json4s.Extraction$.customOrElse(Extraction.scala:606) 在 org.json4s.Extraction$.extract(Extraction.scala:392) 在 org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:514) 在 org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546) 在 org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546) 在 scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) 在 scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) 在 scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) 在 scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48) 在 scala.collection.TraversableLike$class.map(TraversableLike.scala:234) 在 scala.collection.AbstractTraversable.map(Traversable.scala:104) 在 org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546) 在 org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597) 在 org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:400) 在 org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:392) 在 org.json4s.Extraction$.customOrElse(Extraction.scala:606) 在 org.json4s.Extraction$.extract(Extraction.scala:392) 在 org.json4s.Extraction$.extract(Extraction.scala:39) 在 org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21) 在 A$A7$A$A7.decode(json4sgenerics.sc:24) 在 A$A7$A$A7.resultListProduct2$lzycompute(json4sgenerics.sc:37) 在 A$A7$A$A7.resultListProduct2(json4sgenerics.sc:37) 在 A$A7$A$A7.get$$instance$$resultListProduct2(json4sgenerics.sc:36) 在 A$A7$.main(json4sgenerics.sc:92) 在 A$A7.main(json4sgenerics.sc) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:497) 在 org.jetbrains.plugins.scala.worksheet.MyWorksheetRunner.main(MyWorksheetRunner.java:22)

【问题讨论】:

    标签: json scala generics json4s


    【解决方案1】:

    问题是您确实希望将Manifest 传递给decode,但您可能不希望它进入

    case class ResultList[T: Manifest](meta: Meta, result: List[T])
    

    问题是这段代码实际上被编译成类似的东西

    case class ResultList[T](meta: Meta, result: List[T])(implicit evidence: Manifest[T])
    

    而这个implicit参数evidence正是json4s无法从你的JSON中弄清楚如何为你提供的(此时它也不能使用隐式解析,因为它只在编译时完成时间)。

    因此,如果您将 ResultList 更改为

    case class ResultList[T](meta: Meta, result: List[T])
    

    我希望你的代码只要T 绑定到 Json4s 可以提取的东西就可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多