问题
I can't seem to write proper case classes for this particular Json payload. I believe it has something to do with the first index in the array, which doesn't have a key string. Any ideas on how to remedy this? For reference, I am using Scala 2.10.4, Akka 2.3.2, Spray 1.3.1 and Lift-Json 2.6. The Json I am attempting to extract is from Mailgun's Events API. Edit: the core question is how do I extract to a case class with no key in the Json? My code follows:
import net.liftweb.json._
case class Paging(next : String, previous : String)
case class DeliveryEnvelope(transport : String, sender : String, `sending-ip` : String)
case class DeliveryIndex(tags : List[String], envelope : DeliveryEnvelope)
case class DeliveryStatus(message : String, code : Int, description : String)
case class Flags(`is-authenticated` : Boolean, `is-test-mode` : Boolean)
case class DeliveryMessage(headers : Headers, attachments : Option[List[Object]], recipients : List[String], size : Long)
case class Headers(to : String, `message-id` : String, from : String, subject : String)
case class DeliveryData(index : DeliveryIndex, `delivery-status` : DeliveryStatus,
campaigns : List[String], `user-variables` : Object, flags : Flags, timestamp : Double,
message : DeliveryMessage, recipient : String, event : String)
case class Delivered(items: List[DeliveryData], paging: Paging)
object Main extends App {
implicit val formats = DefaultFormats
val json = parse(
""" {
"items": [
{
"tags": [],
"envelope": {
"transport": "smtp",
"sender": "postmaster@samples.mailgun.org",
"sending-ip": "184.173.153.199"
},
"delivery-status": {
"message": "",
"code": 0,
"description": null
},
"campaigns": [],
"user-variables": {},
"flags": {
"is-authenticated": true,
"is-test-mode": false
},
"timestamp": 1377208314.173742,
"message": {
"headers": {
"to": "recipient@example.com",
"message-id": "20130822215151.29325.59996@samples.mailgun.org",
"from": "sender@example.com",
"subject": "Sample Message"
},
"attachments": [],
"recipients": [
"recipient@example.com"
],
"size": 31143
},
"recipient": "recipient@example.com",
"event": "delivered"
}
],
"paging": {
"next": "https://api.mailgun.net/v2/samples.mailgun.org/events/W3siYiI6ICIy",
"previous": "https://api.mailgun.net/v2/samples.mailgun.org/events/W3siYiI6"
}
} """)
println(compactRender(json))
println(json.extract[Delivered])
And the output:
{"items":[{"tags":[],"envelope":{"transport":"smtp","sender":"postmaster@samples.mailgun.org","sending-ip":"184.173.153.199"},"delivery-status":{"message":"","code":0,"description":null},"campaigns":[],"user-variables":{},"flags":{"is-authenticated":true,"is-test-mode":false},"timestamp":1.377208314173742E9,"message":{"headers":{"to":"recipient@example.com","message-id":"20130822215151.29325.59996@samples.mailgun.org","from":"sender@example.com","subject":"Sample Message"},"attachments":[],"recipients":["recipient@example.com"],"size":31143},"recipient":"recipient@example.com","event":"delivered"}],"paging":{"next":"https://api.mailgun.net/v2/samples.mailgun.org/events/W3siYiI6ICIy","previous":"https://api.mailgun.net/v2/samples.mailgun.org/events/W3siYiI6"}}
Exception in thread "main" net.liftweb.json.MappingException: No usable value for items
No usable value for index
No usable value for envelope
No usable value for transport
Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:317)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
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.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:315)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$extract0(Extraction.scala:366)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$extract0(Extraction.scala:199)
at net.liftweb.json.Extraction$.extract(Extraction.scala:43)
at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:312)
at Main$delayedInit$body.apply(Main.scala:87)
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(Main.scala:30)
at Main.main(Main.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: net.liftweb.json.MappingException: No usable value for index
No usable value for envelope
No usable value for transport
Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:317)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
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.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:315)
at net.liftweb.json.Extraction$$anonfun$21.apply(Extraction.scala:305)
at net.liftweb.json.Extraction$$anonfun$21.apply(Extraction.scala:305)
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.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at net.liftweb.json.Extraction$.newCollection$1(Extraction.scala:305)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:322)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
... 30 more
Caused by: net.liftweb.json.MappingException: No usable value for envelope
No usable value for transport
Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:317)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
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.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:315)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
... 51 more
Caused by: net.liftweb.json.MappingException: No usable value for transport
Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:357)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:317)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
at net.liftweb.json.Extraction$$anonfun$14.apply(Extraction.scala:253)
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.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:253)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:286)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:315)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
... 63 more
Caused by: net.liftweb.json.MappingException: Did not find value which can be converted into java.lang.String
at net.liftweb.json.Meta$.fail(Meta.scala:191)
at net.liftweb.json.Extraction$.convert(Extraction.scala:403)
at net.liftweb.json.Extraction$.net$liftweb$json$Extraction$$build$1(Extraction.scala:314)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:351)
... 75 more
回答1:
Thank you all for contributing (or just viewing) my question. I have solved my issue by looping through just the data part of the Json.
val json = parse(STRING HERE)
val elements = (json \\ "items").children
for(item <- elements) {
val data = item.extract[ClickData]
Hopefully this helps anyone else with this or a similar question.
回答2:
You are mapping each item to an instance of DeliveryData, but in DeliveryData:
- You have a non-Optional index field that there is no value for in the corresponding JSON. If that value is optional, it should be defined as Option[DeliveryIndex]
- You have no field to map the envelope information contained in the JSON. You've created a DeliveryEnvelope case class but it's only referenced by the DeliveryIndex class, and the index field doesn't exists in the JSON you posted.
来源:https://stackoverflow.com/questions/25299474/using-lift-json-with-case-classes