简体   繁体   English

JSON转换为case类,并使用json4s进行泛型解码

[英]JSON to case class with generics decoding with json4s

I'm trying to build a json to case class en/decoder using json4s Using generics icw Manifest seems to work for ordinary types/classes, but more complex configs seem to fail. 我正在尝试使用json4s构建json来区分大小写类en / decoder。使用泛型icw清单似乎适用于普通类型/类,但是更复杂的配置似乎失败了。

How can I use json4s combined with extracting more complex types from json strings? 如何结合使用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))) 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))) resultListProduct:ResultListProduct = ResultListProduct(Meta(2),List(Product(123),Product(456)))

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

org.json4s.package$MappingException: No usable value for evidence$1 org.json4s.package $ MappingException:没有可用的证据$ 1

No constructor for type Manifest[User], JNothing 没有Manifest [User]类型的构造函数,JNothing

... ...

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

org.json4s.package$MappingException: No usable value for evidence$1 No constructor for type Manifest[Product], JNothing at org.json4s.reflect.package$.fail(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:91) at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:522) at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:542) at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:542) at scala.collection.TraversableLike$$anonfun$map$1.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230) at scala.collection.TraversableLike$$anonfun$map$1.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230) at scala.collection.mutabl 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:542) 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.mutabl e.ResizableArray$class.foreach(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:55) at scala.collection.mutable.ArrayBuffer.foreach(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:44) at scala.collection.TraversableLike$class.map(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230) at scala.collection.AbstractTraversable.map(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:100) at org.json4s.Extraction$ClassInstanceBuilder.instantiate(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:542) at org.json4s.Extraction$ClassInstanceBuilder.result(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:593) at org.json4s.Extraction$$anonfun$extract$6.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:396) at org.json4s.Extraction$$anonfun$extract$6.apply(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgeneric e.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。申请(/用户/ tomlous /开发/斯卡拉/ testjes / src目录/主/斯卡拉/ json4sgeneric s.sc:388) at org.json4s.Extraction$.customOrElse(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:602) at org.json4s.Extraction$.extract(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:388) at worksheet.worksheet(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:35) s.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)

Caused by: org.json4s.package$MappingException: No constructor for type Manifest[Product], JNothing at org.json4s.reflect.package$.fail(package.scala:95) at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$org$json4s$Extraction$ClassInstanceBuilder$$constructor$1.apply(Extraction.scala:477) at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$org$json4s$Extraction$ClassInstanceBuilder$$constructor$1.apply(Extraction.scala:477) at scala.Option.getOrElse(Option.scala:121) at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$constructor(Extraction.scala:477) at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:532) at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597) at org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:400) at org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:392) at org.json4s.Extraction$.customOrElse(Extraction.scala:606) at org.json4s.Extraction$.extract(Ex 由以下原因引起:org.json4s.package $ MappingException:类型Manifest [Product]没有构造函数,org.json4s.reflect.package $ .fail(package.scala:95)处的JNothing在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 org.json4s上的.instantiate(Extraction.scala:532).org.json4s上的Extraction $ ClassInstanceBuilder.result(Extraction.scala:597).org上的Extraction $$ anonfun $ extract $ 6.apply(Extraction.scala:400)。 org.json4s.Extraction $ .customOrElse(Extraction.scala:606)的json4s.Extraction $$ anonfun $ extract $ 6.apply(Extraction.scala:392)在org.json4s.Extraction $ .extract(Ex traction.scala:392) at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:514) at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546) at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48) at scala.collection.TraversableLike$class.map(TraversableLike.scala:234) at scala.collection.AbstractTraversable.map(Traversable.scala:104) at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546) at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597) at org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:4 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。在scala.collection.mutable.ResizableArray $ class.foreach(ResizableArray.scala:59)处的TraversableLike $$ anonfun $ map $ 1.apply(TraversableLike.scala:234)在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:4 00) at org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:392) at org.json4s.Extraction$.customOrElse(Extraction.scala:606) at org.json4s.Extraction$.extract(Extraction.scala:392) at org.json4s.Extraction$.extract(Extraction.scala:39) at org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21) at A$A7$A$A7.decode(json4sgenerics.sc:24) at A$A7$A$A7.resultListProduct2$lzycompute(json4sgenerics.sc:37) at A$A7$A$A7.resultListProduct2(json4sgenerics.sc:37) at A$A7$A$A7.get$$instance$$resultListProduct2(json4sgenerics.sc:36) at A$A7$.main(json4sgenerics.sc:92) at A$A7.main(json4sgenerics.sc) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.jetbrains.plugins.scala.worksheet.MyWorksheetRunner.main(MyWorksheetRunner.java:22) 00)在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(本地方法)位于org.jetbrains的java.lang.reflect.Method.invoke(Method.java:497)处的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)处的sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) .plugins.scala.worksheet.MyWorksheetRunner.main(MyWorksheetRunner.java:22)

The problem is that you do want Manifest to be passed to decode but you probably don't want it in 问题是您确实希望将Manifest传递给decode但您可能不希望将其传递给

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

The thing is that this code is actually compiled to something like 问题是该代码实际上已编译为类似

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

and this implicit parameter evidence is exactly what json4s can't figure out how to provide for you from your JSON (and at this point it can't use implicit resolution as well because it is done only at compile time). 而且这个implicit参数evidence正是json4s无法弄清楚如何从JSON提供给您的(这时它也不能使用隐式解析,因为它仅在编译时完成)。

So if you change your ResultList to 因此,如果将ResultList更改为

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

I expect that yout code will work as long as T is bound to something that Json4s can extract. 我希望只要T绑定到Json4s可以提取的内容,您的代码就可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM