Json4s: scala 2.10: obtendo "NoSuchFieldException: MODULE$" ao extrair json na classe case

Criado em 31 jan. 2013  ·  10Comentários  ·  Fonte: json4s/json4s

estou recebendo a seguinte exceção ao fazer o seguinte no scala 2.10:

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

eu fiz algumas escavações e estranhamente, o campo estático chamado "MODULE$" que está sempre presente na classe cujo nome termina com '$' antes do scala 2.10 não estar mais lá. json4s parece confiar nele para fazer os bits de extração e, portanto, a exceção. eu acho que o melhor curso de ação para 2.10 pode ser usar a nova API de reflexão scala em vez da java. no entanto, há uma solução rápida que me fará passar o dia?

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

Comentários muito úteis

eu encontrei uma solução alternativa: a classe case que eu defini é na verdade uma aninhada (dentro da classe def). se eu movê-lo para o nível superior, a extração funciona.

Todos 10 comentários

eu encontrei uma solução alternativa: a classe case que eu defini é na verdade uma aninhada (dentro da classe def). se eu movê-lo para o nível superior, a extração funciona.

Atualmente, estou enfrentando o mesmo problema, o que é meio problemático ao trabalhar em cenários modulares, como, por exemplo,

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

Quaisquer sugestões (exceto mover a classe de caso para o nível superior) são muito bem-vindas.

qual versão do json4s você está usando? Eu pensei que consertei isso em 3.2.1

Acabei de verificar com 3.2.1 e ainda recebo o seguinte rastreamento de pilha:

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

Obrigado por reagir tão rápido!

Oh, o 3.2.1 foi lançado?
O README diz apenas cerca de 3.1.0.

@ngocdaothanh sim, mas amanhã vai ter um 3.2.2, vou atualizar a versão no readme então.

@afwlehmann No instantâneo atual, adicionei suporte para classes de caso definidas em um trait. Mas eles precisam de formatos personalizados. Vou explicar por que e depois como.

Por quê?

Para classes definidas em uma característica, é um pouco difícil chegar ao objeto companheiro, que é necessário para fornecer valores padrão. Poderíamos apostar neles, mas isso nos leva ao próximo problema, o compilador gera um campo extra no construtor de tais classes de casos. O primeiro campo no construtor dessas classes case é chamado $outer e é do tipo _definiting trait_. Então, de alguma forma, precisamos obter uma instância desse objeto, ingenuamente poderíamos escanear todas as classes e coletar aquelas que estão implementando o traço, mas quando houver mais de uma: qual pegar?

Como?

Optei por estender os formatos para incluir uma lista de mapeamentos complementares para essas classes de caso. Assim, você pode ter formatos que pertencem aos seus módulos e manter os mapeamentos lá. Isso fará com que os valores padrão funcionem e forneça o campo $outer muito necessário.

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

A essência geral da implementação está neste commit: 96c5bbc5439

Vou deixar o bilhete aberto para você muito perto se isso funcionar para você

quando adicionarmos suporte adequado para macros, isso não será um problema, mas até então isso deve funcionar para o seu caso de uso

Maravilhoso! Apenas verificado contra 3.3.0-SNAPSHOT e funciona como um encanto. Você consideraria adicionar sua explicação, incluindo seu exemplo, ao FAQ?

Muito obrigado por sua ajuda instantânea!

PS: Se eu pudesse fecharia o ticket como você sugeriu, mas aparentemente isso só é possível para o OP.

sim, farei isso amanhã quando liberar isso, fiquei sem tempo para hoje :)

Como analisar Json em json4s usando scala

lib


org.json4s
json4s-native_2.11
3.5.0



org.json4s
json4s-jackson_2.11
3.5.0

{
"alimentar": {
"dados": [
{
"id": "56232316996_10154793401636997",
"a partir de": {
"nome": "Sony",
"categoria": "Marca",
"id": "56232316996"
},
"message": "Torne tudo o que você faz simples e perfeito com o Snappy Bug. Disponível em todos os lugares em 7 de abril. #SmurfsMovie ud83dudc1e",
"picture": " https://scontent.xx.fbcdn.net/v/t15.0-10/s130x130/17698699_10154793403671997_6825513772845629440_n.jpg?oh=df0cc008d453ddofdc7c1dc62e7003150&
"link": " https://www.facebook.com/Sony/videos/10154793401636997/ ",
"fonte": " https://video.xx.fbcdn.net/v/t42.1790-2/17652439_614273148767405_7891577135918219264_n.mp4?efg=eyJybHIiOjMwMCwicmxhIjo1MTIsInZlbmNvZGVfdGFnIjoic3ZlX3NkIn0u00253D&rl=300&vabr=153&oh=4821fb61a186abb4eec5c75e71484809&oe=58E207D8 ",
"propriedades": [
{
"nome": "Comprimento",
"texto": "00:53"
}
],
"icon": " https://www.facebook.com/images/icons/video.gif ",
"ações": [
{
"nome": "Comentário",
"link": " https://www.facebook.com/56232316996/posts/10154793401636997 "
},
{
"nome": "Gostei",
"link": " https://www.facebook.com/56232316996/posts/10154793401636997 "
},
{
"nome": "Compartilhar",
"link": " https://www.facebook.com/56232316996/posts/10154793401636997 "
}
],
"privacidade": {
"valor": "",
"Descrição": "",
"amigos": "",
"permitir": "",
"negar": ""
},
"tipo": "vídeo",
"status_type": "added_video",
"object_id": "10154793401636997",
"aplicativo": {
"categoria": "Negócios",
"link": " http://percolate.com/ ",
"name": "Percolar",
"id": "140966572641315"
},
"created_time": "2017-04-01T14:58:43+0000",
"updated_time": "2017-04-01T15:04:30+0000",
"compartilhamentos": {
"contar": 4
},
"is_hidden": falso,
"is_expired": falso,
"gosta": {
"dados": [
{
"id": "1575991392612312",
"name": "Mostafa Mitkees"
},
{
"id": "10202136107064392",
"nome": "Lee Jun Jiat"
},
{
"id": "803230886383593",
"nome": "Alan Teh"
},
{
"id": "491963830956592",
"nome": "Ashwin Kumar"
},
{
"id": "378907082276389",
"name": "Asit Kumar Rout Ray"
},
{
"id": "1383678128601455",
"nome": "Reuben Espinoza"
},
{
"id": "284377675056287",
"name": "Fuat Mehmet Bu00fcyu00fckgu00f6ncu00fc"
},
{
"id": "750971141656153",
"name": "Ronak KaPatel"
},
{
"id": "777260162293873",
"name": "Josu00e9 Marrero"
},
{
"id": "626209014114011",
"name": "Fazal Mehmood"
},
{
"id": "290810434455921",
"name": "Conheça Gaikwad"
},
{
"id": "499613843484091",
"name": "Mohamed Alzantany"
},
{
"id": "328707693980567",
"nome": "Shuvo Sutradhar"
},
{
"id": "599284866870692",
"name": "Anil Kumar Prda"
},
{
"id": "772235059534061",
"nome": "Krishna Soni"
},
{
"id": "112905259114293",
"nome": "Victoria Dale"
},
{
"id": "1477362329219496",
"name": "Eigger Noznev"
},
{
"id": "637712649677736",
"name": "Cu00e9sar Ramos"
},
{
"id": "143463916136734",
"name": "Harshit Kumar"
},
{
"id": "595803490553309",
"name": "Rafael Gonu00e7alves"
},
{
"id": "10152471964605339",
"nome": "Sérgio Paulo Ramos"
},
{
"id": "707469975981873",
"name": "Alemão Carrizo"
},
{
"id": "189046894916898",
"name": "Ideia Ohtman"
},
{
"id": "1573720769567745",
"name": "Daniel Essa"
},
{
"id": "147832419056255",
"nome": "Mody Ahmed"
}
],
"paginação": {
"cursores": {
"antes": "MTU3NTk5MTM5MjYxMjMxMgZDZD",
"depois": "MTQ3ODMyNDE5MDU2MjU1"
},
"next": " https://graph.facebook.com/v2.3/56232316996_10154793401636997/likes?access_token=EAACEdEose0cBACjlK34OPuSbgblWqljej3xCFW8drAj3dZCVPoSGJrU7MEZAJPLnUDoWXdTqv5GFPWLFfw4bFZCivpi4RuPYMuQ3luZABDCMUZAAXC3LpOFN2KQOnrZAvfdsjhVsCeevE1e8q1bvMVHLyoCwGTZAl1rORRdQsuHwJ0x9ce8HPxHZAHumtSaIY0UZD&limit=25&after=MTQ3ODMyNDE5MDU2MjU1 "
}
},
"comentários": {
"dados": [
{
"created_time": "2017-04-01T15:04:30+0000",
"a partir de": {
"nome": "Jamie Walsh",
"id": "10202015774835189"
},
"mensagem": "Steph Hawkins",
"can_remove": falso,
"like_count": 0,
"mensagem_tags": [
{
"id": "389600537878566",
"comprimento": 13,
"nome": "Steph Hawkins",
"deslocamento": 0,
"tipo": "usuário"
}
],
"user_likes": falso,
"id": "10154793401636997_10154793417296997"
}
],
"paginação": {
"cursores": {
"antes": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEF4TlRRM09UTTBNVGN5T1RZANU9UYzZANVFE1TVRBMU9UQTNNUT09",
"depois": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEF4TlRRM09UTTBNVGN5T1RZANU9UYzZANVFE1TVRBMU9UQTNNUT09"
}
}
}
},
{
"id": "56232316996_10154793280231997",
"a partir de": {
"nome": "Yolonda Jones",
"id": "1619018185048449"
},
"message": "meu Dash está morto",
"ações": [
{
"nome": "Comentário",
"link": " https://www.facebook.com/56232316996/posts/10154793280231997 "
},
{
"nome": "Gostei",
"link": " https://www.facebook.com/56232316996/posts/10154793280231997 "
},
{
"nome": "Compartilhar",
"link": " https://www.facebook.com/56232316996/posts/10154793280231997 "
}
],
"privacidade": {
"valor": "",
"Descrição": "",
"amigos": "",
"permitir": "",
"negar": ""
},
"tipo": "estado",
"status_type": "wall_post",
"created_time": "2017-04-01T13:54:06+0000",
"updated_time": "2017-04-01T13:54:06+0000",
"is_hidden": falso,
"is_expired": false
}
],
"paginação": {
"anterior": " 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"
}
analisando json

val JSON = parse(json)
formatos de valor implícito = DefaultFormats
val nomes = (JSON "feed""dados""de""nome")
println(nomes)
val messagesIds = (JSON "feed""data""from") "id"
val mensagens = (JSON "feed""dados") "mensagem"
println(messagesIds.values)

estou obtendo resultado para

Lista (Sony, Yolonda Jones)
Lista(56232316996, 1619018185048449)
List(Faça tudo o que você faz simples e perfeito com Snappy Bug. Disponível em todos os lugares em 7 de abril. #SmurfsMovie 🐞, meu Dash está morto)

Mas iam resultado esperado para assim

for (nome1 <- nomes) println(nome1)
Sony
Yolonda Jones

for (msgstr <- messagesIds) println(msgstr)

56232316996
1619018185048449
mensagens
for (msg <- mensagens) println(msg)
Torne tudo o que você faz simples e perfeito com Snappy Bug. Disponível em todos os lugares em 7 de abril. #SmurfsMovie 🐞
meu traço está morto

Esta página foi útil?
0 / 5 - 0 avaliações