JSON到case类,使用json4s进行泛型解码

时间:2018-01-23 11:10:14

标签: json scala generics json4s

我正在尝试使用json4s构建一个json到case类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:证据$ 1

没有可用值      

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

     

...

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

org.json4s.package $ MappingException:没有可用的证据价值$ 1没有   类型Manifest [Product]的构造函数,JNothing at   org.json4s.reflect.package $ .fail(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:91)     在   org.json4s.Extraction $ ClassInstanceBuilder.org $ json4s $ $提取$$ 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 $表$ 1.适用(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:230)     在   scala.collection.TraversableLike $$ anonfun $表$ 1.适用(/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 $ $提取7.适用(/Users/tomlous/Development/Scala/testjes/src/main/scala/json4sgenerics.sc:396)     在   org.json4s.Extraction $$ anonfun $ $提取7.适用(/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:没有构造函数   类型清单[产品],J没什么   org.json4s.reflect.package $ .fail(package.scala:95)at   org.json4s.Extraction $ ClassInstanceBuilder $$ anonfun $ $组织$ json4s提取$ ClassInstanceBuilder $$构造$ 1.适用(Extraction.scala:477)     在   org.json4s.Extraction $ ClassInstanceBuilder $$ anonfun $ $组织$ json4s提取$ ClassInstanceBuilder $$构造$ 1.适用(Extraction.scala:477)     在scala.Option.getOrElse(Option.scala:121)at   org.json4s.Extraction $ ClassInstanceBuilder.org $ json4s $ $提取$$ ClassInstanceBuilder构造(Extraction.scala:477)     在   org.json4s.Extraction $ ClassInstanceBuilder.instantiate(Extraction.scala:532)     在   org.json4s.Extraction $ ClassInstanceBuilder.result(Extraction.scala:597)     在   org.json4s.Extraction $$ anonfun $ $提取7.适用(Extraction.scala:400)     在   org.json4s.Extraction $$ anonfun $ $提取7.适用(Extraction.scala:392)     在org.json4s.Extraction $ .customOrElse(Extraction.scala:606)at at   org.json4s.Extraction $ .extract(Extraction.scala:392)at   org.json4s.Extraction $ ClassInstanceBuilder.org $ json4s $ $提取$$ 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 $表$ 1.适用(TraversableLike.scala:234)     在   scala.collection.TraversableLike $$ anonfun $表$ 1.适用(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 $ $提取7.适用(Extraction.scala:400)     在   org.json4s.Extraction $$ anonfun $ $提取7.适用(Extraction.scala:392)     在org.json4s.Extraction $ .customOrElse(Extraction.scala:606)at at   org.json4s.Extraction $ .extract(Extraction.scala:392)at   org.json4s.Extraction $ .extract(Extraction.scala:39)at   org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21)     在A $ A7 $ A $ A7.decode(json4sgenerics.sc:24)at   一个$ A7 $ A $ A7.resultListProduct2 $ lzycompute(json4sgenerics.sc:37)at at   一个$ A7 $ A $ A7.resultListProduct2(json4sgenerics.sc:37)at at   一个$ A7 $ A $ A7.get $$实例$$ resultListProduct2(json4sgenerics.sc:36)at at   $ A7 $ .main(json4sgenerics.sc:92)在A $ A7.main(json4sgenerics.sc)at at   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:497)at   org.jetbrains.plugins.scala.worksheet.MyWorksheetRunner.main(MyWorksheetRunner.java:22)

1 个答案:

答案 0 :(得分:1)

问题是您确实希望将// Assuming that type Meeting = { location: string[]; participants: string[]; } const WhatIWantAtTheEnd: Meeting[] = RawDataFromDB .map(meeting => meeting.participants.sort((a, b) => a.localeCompare(b))) // Create a participant sorted list .filter((value, index, array) => index === array.findIndex(compValue => value.every(participant => compValue.includes(participant)))) // strip duplicates .map(sortedParticipants => ({ participants: sortedParticipants, location: RawDataFromDB.filter(raw => raw.participants.every(participant => sortedParticipants.includes(participant))).map(e => e.location) })); 传递给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正是json4s无法弄清楚如何从JSON中提供的(并且此时它不能使用隐式解析好吧,因为它只在编译时完成。)

因此,如果您将evidence更改为

ResultList

我希望只要case class ResultList[T](meta: Meta, result: List[T]) 绑定到Json4s可以提取的东西,你的代码就会起作用。