Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scala 2.10: getting "NoSuchFieldException: MODULE$" while extracting json into case class #22

Closed
weihsiu opened this issue Jan 31, 2013 · 10 comments

Comments

@weihsiu
Copy link

weihsiu commented Jan 31, 2013

i am getting the following exception while doing the following in scala 2.10:

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

i did some digging and strangely enough, the static field named "MODULE$" that is always present in class whose name ends with '$' before scala 2.10 is no longer there. json4s seems to rely on it to do the extraction bits and hence the exception. i think the best course of action for 2.10 might be to use the new scala reflection api instead of the java one. however, it there a quick fix that will get me through the day?

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
@weihsiu
Copy link
Author

weihsiu commented Jan 31, 2013

i've found a workaround: the case class i defined is actually a nested one (inside class def). if i move it to the top level, the extraction works.

@afwlehmann
Copy link

I am currently experiencing the same issue which is kind of problematic when working in modular scenarios like e.g.

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]
}

Any suggestions (except moving the case class to the top-level) are highly welcome.

@casualjim
Copy link
Member

which version of json4s are you using? I thought I fixed this in 3.2.1

@afwlehmann
Copy link

I just checked with 3.2.1 and still get the following stack trace:

[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)

Thanks for reacting so quickly!

@ngocdaothanh
Copy link

Oh has 3.2.1 been released?
The README only says about 3.1.0.

@casualjim
Copy link
Member

@ngocdaothanh yes, but tomorrow there will be a 3.2.2, I'll update the version in the readme then.

@afwlehmann In the current snapshot I've added support for case classes defined in a trait. But they do need custom formats. I'll explain why and then how.

Why?

For classes defined in a trait it's a bit difficult to get to their companion object, which is needed to provide default values. We could punt on those but that brings us to the next problem, the compiler generates an extra field in the constructor of such case classes. The first field in the constructor of those case classes is called $outer and is of type of the defining trait. So somehow we need to get an instance of that object, naively we could scan all classes and collect the ones that are implementing the trait, but when there are more than one: which one to take?

How?

I've chosen to extend the formats to include a list of companion mappings for those case classes. So you can have formats that belong to your modules and keep the mappings in there. That will then make default values work and provide the much needed $outer field.

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

The general gist of the implementation is in this commit: 96c5bbc

I'll leave the ticket open for you too close if this works for you

@casualjim
Copy link
Member

when we add proper support for macros this will be a non-issue, but until then this should work for your use case

@afwlehmann
Copy link

Wonderful! Just checked against 3.3.0-SNAPSHOT and it works like a charm. Would you consider adding your explanation including your example to the FAQ?

Thank you very much for your instant help!

P.S.: If I could I would close the ticket like you've suggested, but apparently that is only possible for the OP.

@casualjim
Copy link
Member

yeah I'll do that tomorrow when I release this, I ran out of time for today :)

@samynathan17
Copy link

samynathan17 commented Apr 1, 2017

How to parse Json in json4s using scala

lib

org.json4s json4s-native_2.11 3.5.0 org.json4s json4s-jackson_2.11 3.5.0

{
"feed": {
"data": [
{
"id": "56232316996_10154793401636997",
"from": {
"name": "Sony",
"category": "Brand",
"id": "56232316996"
},
"message": "Make everything you do simple & seamless with Snappy Bug. Available everywhere April 7. #SmurfsMovie \ud83d\udc1e",
"picture": "https://scontent.xx.fbcdn.net/v/t15.0-10/s130x130/17698699_10154793403671997_6825513772845629440_n.jpg?oh=df0cc008d453ddfdc7c1dc62e7003150&oe=5957B479",
"link": "https://www.facebook.com/Sony/videos/10154793401636997/",
"source": "https://video.xx.fbcdn.net/v/t42.1790-2/17652439_614273148767405_7891577135918219264_n.mp4?efg=eyJybHIiOjMwMCwicmxhIjo1MTIsInZlbmNvZGVfdGFnIjoic3ZlX3NkIn0\u00253D&rl=300&vabr=153&oh=4821fb61a186abb4eec5c75e71484809&oe=58E207D8",
"properties": [
{
"name": "Length",
"text": "00:53"
}
],
"icon": "https://www.facebook.com/images/icons/video.gif",
"actions": [
{
"name": "Comment",
"link": "https://www.facebook.com/56232316996/posts/10154793401636997"
},
{
"name": "Like",
"link": "https://www.facebook.com/56232316996/posts/10154793401636997"
},
{
"name": "Share",
"link": "https://www.facebook.com/56232316996/posts/10154793401636997"
}
],
"privacy": {
"value": "",
"description": "",
"friends": "",
"allow": "",
"deny": ""
},
"type": "video",
"status_type": "added_video",
"object_id": "10154793401636997",
"application": {
"category": "Business",
"link": "http://percolate.com/",
"name": "Percolate",
"id": "140966572641315"
},
"created_time": "2017-04-01T14:58:43+0000",
"updated_time": "2017-04-01T15:04:30+0000",
"shares": {
"count": 4
},
"is_hidden": false,
"is_expired": false,
"likes": {
"data": [
{
"id": "1575991392612312",
"name": "Mostafa Mitkees"
},
{
"id": "10202136107064392",
"name": "Lee Jun Jiat"
},
{
"id": "803230886383593",
"name": "Alan Teh"
},
{
"id": "491963830956592",
"name": "Ashwin Kumar"
},
{
"id": "378907082276389",
"name": "Asit Kumar Rout Ray"
},
{
"id": "1383678128601455",
"name": "Reuben Espinoza"
},
{
"id": "284377675056287",
"name": "Fuat Mehmet B\u00fcy\u00fckg\u00f6nc\u00fc"
},
{
"id": "750971141656153",
"name": "Ronak KaPatel"
},
{
"id": "777260162293873",
"name": "Jos\u00e9 Marrero"
},
{
"id": "626209014114011",
"name": "Fazal Mehmood"
},
{
"id": "290810434455921",
"name": "Meet Gaikwad"
},
{
"id": "499613843484091",
"name": "Mohamed Alzantany"
},
{
"id": "328707693980567",
"name": "Shuvo Sutradhar"
},
{
"id": "599284866870692",
"name": "Anil Kumar Prda"
},
{
"id": "772235059534061",
"name": "Krrishna Soni"
},
{
"id": "112905259114293",
"name": "Victoria Dale"
},
{
"id": "1477362329219496",
"name": "Eigger Noznev"
},
{
"id": "637712649677736",
"name": "C\u00e9sar Ramos"
},
{
"id": "143463916136734",
"name": "Harshit Kumar"
},
{
"id": "595803490553309",
"name": "Rafael Gon\u00e7alves"
},
{
"id": "10152471964605339",
"name": "Sergio Paul Ramos"
},
{
"id": "707469975981873",
"name": "German Carrizo"
},
{
"id": "189046894916898",
"name": "Ohtman Idea"
},
{
"id": "1573720769567745",
"name": "Danial Essa"
},
{
"id": "147832419056255",
"name": "Mody Ahmed"
}
],
"paging": {
"cursors": {
"before": "MTU3NTk5MTM5MjYxMjMxMgZDZD",
"after": "MTQ3ODMyNDE5MDU2MjU1"
},
"next": "https://graph.facebook.com/v2.3/56232316996_10154793401636997/likes?access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&limit=25&after=MTQ3ODMyNDE5MDU2MjU1"
}
},
"comments": {
"data": [
{
"created_time": "2017-04-01T15:04:30+0000",
"from": {
"name": "Jamie Walsh",
"id": "10202015774835189"
},
"message": "Steph Hawkins",
"can_remove": false,
"like_count": 0,
"message_tags": [
{
"id": "389600537878566",
"length": 13,
"name": "Steph Hawkins",
"offset": 0,
"type": "user"
}
],
"user_likes": false,
"id": "10154793401636997_10154793417296997"
}
],
"paging": {
"cursors": {
"before": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEF4TlRRM09UTTBNVGN5T1RZANU9UYzZANVFE1TVRBMU9UQTNNUT09",
"after": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEF4TlRRM09UTTBNVGN5T1RZANU9UYzZANVFE1TVRBMU9UQTNNUT09"
}
}
}
},
{
"id": "56232316996_10154793280231997",
"from": {
"name": "Yolonda Jones",
"id": "1619018185048449"
},
"message": "my Dash is dead",
"actions": [
{
"name": "Comment",
"link": "https://www.facebook.com/56232316996/posts/10154793280231997"
},
{
"name": "Like",
"link": "https://www.facebook.com/56232316996/posts/10154793280231997"
},
{
"name": "Share",
"link": "https://www.facebook.com/56232316996/posts/10154793280231997"
}
],
"privacy": {
"value": "",
"description": "",
"friends": "",
"allow": "",
"deny": ""
},
"type": "status",
"status_type": "wall_post",
"created_time": "2017-04-01T13:54:06+0000",
"updated_time": "2017-04-01T13:54:06+0000",
"is_hidden": false,
"is_expired": false
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.3/56232316996/feed?limit=2&since=1491058723&access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&__paging_token=enc_AdCnFuVgS6s0EENDKxeFnsXwqG8XtiGsOxVd00AGsBzNou3clnZBn0vJhflw5CZBOGR6A6Q42ZBWSdiAjla1CpBp3ZBj&__previous=1",
"next": "https://graph.facebook.com/v2.3/56232316996/feed?limit=2&access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&until=1491054846&__paging_token=enc_AdAK9TUjksilIGXsICFeX3rAS8gWW1tAOyC7GBlZA2b6XkrBfT1TpfEEU2709L5eZBt49tqvH2eCC2bqOgfJPUXD40"
}
},
"id": "56232316996"
}
parsing json

val JSON = parse(json)
implicit val formats = DefaultFormats
val names = (JSON \ "feed""data""from""name")
println(names)
val messagesIds = (JSON \ "feed""data""from") \ "id"
val messages = (JSON \ "feed""data") \ "message"
println(messagesIds.values)

iam getting result for

List(Sony, Yolonda Jones)
List(56232316996, 1619018185048449)
List(Make everything you do simple & seamless with Snappy Bug. Available everywhere April 7. #SmurfsMovie 🐞, my Dash is dead)

But iam expected result for like this

for (name1 <- names) println(name1)
Sony
Yolonda Jones

for (msgid <- messagesIds) println(msgid)

56232316996
1619018185048449
messages
for (msg <- messages) println(msg)
Make everything you do simple & seamless with Snappy Bug. Available everywhere April 7. #SmurfsMovie 🐞
my Dash is dead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

5 participants