Json4s: scala 2.10:在将 json 提取到案例类时获取“NoSuchFieldException:MODULE$”

创建于 2013-01-31  ·  10评论  ·  资料来源: json4s/json4s

在 scala 2.10 中执行以下操作时出现以下异常:

case class Post(text: String)
parse("""{"text":"hello"}""").extract[Post]

我做了一些挖掘,奇怪的是,在 scala 2.10 不再存在之前,名为“MODULE$”的静态字段始终存在于名称以“$”结尾的类中。 json4s 似乎依赖它来执行提取位,因此是例外。 我认为 2.10 的最佳做法可能是使用新的 scala 反射 api 而不是 java 的。 但是,有一个快速的解决方法可以让我度过一天吗?

Caused by: java.lang.NoSuchFieldException: MODULE$
    at java.lang.Class.getField(Class.java:1537)
    at org.json4s.Meta$$anonfun$mappingOf$1$$anonfun$8.apply(Meta.scala:208)
    at org.json4s.Meta$$anonfun$mappingOf$1.apply(Meta.scala:207)
    at org.json4s.Meta$$anonfun$mappingOf$1.apply(Meta.scala:195)
    at org.json4s.Meta$Memo.memoize(Meta.scala:240)
    at org.json4s.Meta$.mappingOf(Meta.scala:195)
    at org.json4s.Extraction$.org$json4s$Extraction$$mkMapping$1(Extraction.scala:207)
    at org.json4s.Extraction$.org$json4s$Extraction$$extract0(Extraction.scala:212)
    at org.json4s.Extraction$.extract(Extraction.scala:48)
    ... 84 more

最有用的评论

我找到了一种解决方法:我定义的案例类实际上是一个嵌套类(在类 def 中)。 如果我将它移到顶层,则提取工作。

所有10条评论

我找到了一种解决方法:我定义的案例类实际上是一个嵌套类(在类 def 中)。 如果我将它移到顶层,则提取工作。

我目前遇到同样的问题,这在模块化场景中工作时会出现问题,例如

import org.json4s._
import org.json4s.native.JsonMethods._

trait PersonModule {
  case class Person(name: String, age: Int)
}

object Main extends App with PersonModule {
  implicit val formats = DefaultFormats
  val json = """{"name":"joe","age":15}"""
  val p: Person = parse(json).extract[Person]
}

非常欢迎任何建议(除了将案例类移到顶层)。

您使用的是哪个版本的 json4s? 我以为我在 3.2.1 中修复了这个问题

我刚刚检查了 3.2.1,仍然得到以下堆栈跟踪:

[error] (run-main) org.json4s.package$MappingException: No usable value for $outer
[error] No constructor for type PersonModule, JNothing
org.json4s.package$MappingException: No usable value for $outer
No constructor for type PersonModule, JNothing
    at org.json4s.reflect.package$.fail(package.scala:75)
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:380)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$11.apply(Extraction.scala:388)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$11.apply(Extraction.scala:388)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
    at scala.collection.AbstractTraversable.map(Traversable.scala:105)
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$instantiate(Extraction.scala:388)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$5.apply(Extraction.scala:416)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$5.apply(Extraction.scala:413)
    at org.json4s.Extraction$.org$json4s$Extraction$$customOrElse(Extraction.scala:425)
    at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:413)
    at org.json4s.Extraction$.extract(Extraction.scala:281)
    at org.json4s.Extraction$.extract(Extraction.scala:45)
    at org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21)
    at Main$delayedInit$body.apply(JsonProblem.scala:16)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
    at scala.App$class.main(App.scala:71)
    at Main$.main(JsonProblem.scala:10)
    at Main.main(JsonProblem.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
Caused by: org.json4s.package$MappingException: No constructor for type PersonModule, JNothing
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$constructor(Extraction.scala:341)
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$instantiate(Extraction.scala:386)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$5.apply(Extraction.scala:416)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$5.apply(Extraction.scala:413)
    at org.json4s.Extraction$.org$json4s$Extraction$$customOrElse(Extraction.scala:425)
    at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:413)
    at org.json4s.Extraction$.extract(Extraction.scala:281)
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:374)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$11.apply(Extraction.scala:388)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$11.apply(Extraction.scala:388)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
    at scala.collection.AbstractTraversable.map(Traversable.scala:105)
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$instantiate(Extraction.scala:388)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$5.apply(Extraction.scala:416)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$5.apply(Extraction.scala:413)
    at org.json4s.Extraction$.org$json4s$Extraction$$customOrElse(Extraction.scala:425)
    at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:413)
    at org.json4s.Extraction$.extract(Extraction.scala:281)
    at org.json4s.Extraction$.extract(Extraction.scala:45)
    at org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21)
    at Main$delayedInit$body.apply(JsonProblem.scala:16)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
    at scala.App$class.main(App.scala:71)
    at Main$.main(JsonProblem.scala:10)
    at Main.main(JsonProblem.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)

谢谢你这么快的反应!

哦,3.2.1发布了吗?
自述文件只说大约 3.1.0。

@ngocdaothanh是的,但是明天会有 3.2.2,然后我会更新自述文件中的版本。

@afwlehmann在当前快照中,我添加了对特征中定义的案例类的支持。 但他们确实需要自定义格式。 我将解释为什么以及如何。

为什么?

对于在 trait 中定义的类,获取它们的伴生对象有点困难,这是提供默认值所必需的。 我们可以对这些进行抨击,但这会给我们带来下一个问题,编译器会在此类案例类的构造函数中生成一个额外的字段。 这些案例类的构造函数中的第一个字段称为$outer ,并且是_定义特征_的类型。 因此,我们需要以某种方式获取该对象的实例,天真地我们可以扫描所有类并收集实现该特征的类,但是当有多个类时:取哪个?

如何?

我选择扩展格式以包含这些案例类的伴随映射列表。 因此,您可以拥有属于您的模块的格式并将映射保留在其中。 这将使默认值起作用并提供急需的$outer字段。

trait SharedModule {
  case class SharedObj(name: String, visible: Boolean = false)
}

object PingPongGame extends SharedModule
implicit val formats: Formats = 
  DefaultFormats.withCompanions(classOf[PingPongGame.SharedObj] -> PingPongGame)

val inst = PingPongGame.SharedObj("jeff", visible = true)
val extr = Extraction.decompose(inst)
extr must_== JObject("name" -> JString("jeff"), "visible" -> JBool(true))
extr.extract[PingPongGame.SharedObj] must_== inst

实现的一般要点在此提交中:96c5bbc5439

如果这对你有用,我会把票给你开得太近

当我们添加对宏的适当支持时,这将不是问题,但在此之前,这应该适用于您的用例

精彩的! 刚刚检查了 3.3.0-SNAPSHOT,它就像一个魅力。 您会考虑将您的解释(包括您的示例)添加到常见问题解答中吗?

非常感谢您的即时帮助!

PS:如果可以的话,我会按照您的建议关闭票,但显然这仅适用于 OP。

是的,我明天发布这个时会这样做,我今天没时间了:)

如何使用scala解析json4s中的Json


org.json4s
json4s-native_2.11
3.5.0



org.json4s
json4s-jackson_2.11
3.5.0

{
“喂养”: {
“数据”: [
{
"id": "56232316996_10154793401636997",
“从”: {
“名称”:“索尼”,
“类别”:“品牌”,
“id”:“56232316996”
},
"message": "使用 Snappy Bug 让您所做的一切变得简单和无缝。4 月 7 日随处可用。#SmurfsMovie ud83dudc1e",
“图片”:“ https://scontent.xx.fbcdn.net/v/t15.0-10/s130x130/17698699_10154793403671997_6825513772845629440_n.jpg?oh=df0cc008d453ddfdc7c1dc62e7003150&oe=5957B
“链接”:“ https://www.facebook.com/Sony/videos/10154793401636997/ ”,
“源”: “ https://video.xx.fbcdn.net/v/t42.1790-2/17652439_614273148767405_7891577135918219264_n.mp4?efg=eyJybHIiOjMwMCwicmxhIjo1MTIsInZlbmNvZGVfdGFnIjoic3ZlX3NkIn0u00253D&rl=300&vabr=153&oh=4821fb61a186abb4eec5c75e71484809&oe=58E207D8 ”,
“特性”: [
{
“名称”:“长度”,
“文本”:“00:53”
}
],
“图标”:“ https://www.facebook.com/images/icons/video.gif ”,
“行动”:[
{
“名称”:“评论”,
“链接”:“ https://www.facebook.com/56232316996/posts/10154793401636997
},
{
“名称”:“喜欢”,
“链接”:“ https://www.facebook.com/56232316996/posts/10154793401636997
},
{
“名称”:“分享”,
“链接”:“ https://www.facebook.com/56232316996/posts/10154793401636997
}
],
“隐私”: {
“价值”: ””,
“描述”: ””,
“朋友们”: ””,
“允许”: ””,
“否定”: ””
},
“类型”:“视频”,
“status_type”:“add_video”,
"object_id": "10154793401636997",
“应用”: {
“类别”:“商业”,
“链接”:“ http://percolate.com/ ”,
“名称”:“渗透”,
“id”:“140966572641315”
},
"created_time": "2017-04-01T14:58:43+0000",
"updated_time": "2017-04-01T15:04:30+0000",
“分享”: {
“计数”:4
},
“is_hidden”:假,
“is_expired”:假,
“喜欢”:{
“数据”: [
{
"id": "1575991392612312",
“名称”:“穆斯塔法·米基斯”
},
{
"id": "10202136107064392",
“姓名”:“李俊佳”
},
{
"id": "803230886383593",
“姓名”:“艾伦·德”
},
{
“id”:“491963830956592”,
“名称”:“阿什温库马尔”
},
{
"id": "378907082276389",
“名称”:“Asit Kumar Rout Ray”
},
{
"id": "1383678128601455",
“名称”:“鲁本·埃斯皮诺萨”
},
{
“id”:“284377675056287”,
“名称”:“法特·穆罕默德 Bu00fcyu00fckgu00f6ncu00fc”
},
{
“id”:“750971141656153”,
“名称”:“罗纳克·卡帕特尔”
},
{
"id": "777260162293873",
“名称”:“Josu00e9 Marrero”
},
{
"id": "626209014114011",
“名称”:“法扎尔·梅赫穆德”
},
{
“id”:“290810434455921”,
“名称”:“认识 Gaikwad”
},
{
"id": "499613843484091",
“名称”:“穆罕默德·阿尔占塔尼”
},
{
"id": "328707693980567",
“名称”:“Shuvo Sutradhar”
},
{
"id": "599284866870692",
“名称”:“阿尼尔·库马尔·普达”
},
{
"id": "772235059534061",
“名称”:“克里希纳·索尼”
},
{
"id": "112905259114293",
“名称”:“维多利亚戴尔”
},
{
"id": "1477362329219496",
“名称”:“艾格·诺兹涅夫”
},
{
“id”:“637712649677736”,
“名称”:“Cu00e9sar 拉莫斯”
},
{
"id": "143463916136734",
“名称”:“哈希特库马尔”
},
{
“id”:“595803490553309”,
“名称”:“拉斐尔 Gonu00e7alves”
},
{
"id": "10152471964605339",
“名称”:“塞尔吉奥·保罗·拉莫斯”
},
{
"id": "707469975981873",
“名称”:“德国卡里佐”
},
{
"id": "189046894916898",
“名称”:“奥特曼理念”
},
{
"id": "1573720769567745",
“名称”:“丹尼尔·埃萨”
},
{
"id": "147832419056255",
“姓名”:“莫迪·艾哈迈德”
}
],
“分页”:{
“光标”:{
“之前”:“MTU3NTk5MTM5MjYxMjMxMgZDZD”,
“之后”:“MTQ3ODMyNDE5MDU2MjU1”
},
“下一个”: “ https://graph.facebook.com/v2.3/56232316996_10154793401636997/likes?access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&limit=25&after=MTQ3ODMyNDE5MDU2MjU1
}
},
“评论”: {
“数据”: [
{
"created_time": "2017-04-01T15:04:30+0000",
“从”: {
“名称”:“杰米沃尔什”,
“id”:“10202015774835189”
},
“消息”:“斯蒂芬霍金斯”,
“can_remove”:假,
“like_count”:0,
“消息标签”:[
{
"id": "389600537878566",
“长度”:13,
“名称”:“斯蒂芬霍金斯”,
“偏移”:0,
“类型”:“用户”
}
],
“用户喜欢”:假,
“id”:“10154793401636997_10154793417296997”
}
],
“分页”:{
“光标”:{
“之前”:“WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEF4TlRRM09UTTBNVGN5T1RZANU9UYzZANVFE1TVRBMU9UQTNNUT09”,
“之后”:“WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEF4TlRRM09UTTBNVGN5T1RZANU9UYzZANVFE1TVRBMU9UQTNNUT09”
}
}
}
},
{
"id": "56232316996_10154793280231997",
“从”: {
“名称”:“约隆达琼斯”,
“id”:“1619018185048449”
},
"message": "我的 Dash 死了",
“行动”:[
{
“名称”:“评论”,
“链接”:“ https://www.facebook.com/56232316996/posts/10154793280231997
},
{
“名称”:“喜欢”,
“链接”:“ https://www.facebook.com/56232316996/posts/10154793280231997
},
{
“名称”:“分享”,
“链接”:“ https://www.facebook.com/56232316996/posts/10154793280231997
}
],
“隐私”: {
“价值”: ””,
“描述”: ””,
“朋友们”: ””,
“允许”: ””,
“否定”: ””
},
“类型”:“状态”,
"status_type": "wall_post",
"created_time": "2017-04-01T13:54:06+0000",
"updated_time": "2017-04-01T13:54:06+0000",
“is_hidden”:假,
“is_expired”:假
}
],
“分页”:{
“前面的”:“ https://graph.facebook.com/v2.3/56232316996/feed?limit=2&since=1491058723&access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&__paging_token=enc_AdCnFuVgS6s0EENDKxeFnsXwqG8XtiGsOxVd00AGsBzNou3clnZBn0vJhflw5CZBOGR6A6Q42ZBWSdiAjla1CpBp3ZBj&__previous=1
“下一个”: “ https://graph.facebook.com/v2.3/56232316996/feed?limit=2&access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&until=1491054846&__paging_token=enc_AdAK9TUjksilIGXsICFeX3rAS8gWW1tAOyC7GBlZA2b6XkrBfT1TpfEEU2709L5eZBt49tqvH2eCC2bqOgfJPUXD40
}
},
“id”:“56232316996”
}
解析json

val JSON = 解析(json)
隐式 val 格式 = DefaultFormats
val names = (JSON "feed""data""from""name")
println(名字)
val messagesIds = (JSON "feed""data""from") "id"
val messages = (JSON "feed""data") "message"
println(messagesIds.values)

我正在得到结果

名单(索尼,约隆达琼斯)
名单(56232316996、1619018185048449)
列表(使用 Snappy Bug 让您所做的一切变得简单和无缝。4 月 7 日随处可用。#SmurfsMovie 🐞,我的 Dash 已死)

但是我是这样的预期结果

for (name1 <- 名称) println(name1)
索尼
约隆达·琼斯

for (msgid <- messagesIds) println(msgid)

56232316996
1619018185048449
消息
for (msg <- 消息) println(msg)
使用 Snappy Bug 让您所做的一切变得简单而无缝。 4 月 7 日随处可见。#SmurfsMovie 🐞
我的 Dash 死了

此页面是否有帮助?
0 / 5 - 0 等级