我正在使用以下json对象获取http响应
{
transaction_hash: "fbb36255453bf8ff465d9ca5c427bd0e36cc799fda090cbcd62113f1f3e97cb4",
output_index: 0,
value: 2000000,
asset_id: null,
asset_quantity: null,
addresses: [
"1C4kYhyLftmkn48YarSoLupxHfYFo8kp64"
],
script_hex: "76a914795efb808598d6a24d1734b929fce1d4b713215188ac",
spent: false,
confirmations: 72935
}
这就是我将json对象读入本机scala对象的方法
override def read(value: JsValue): UnspentTXO = {
val jsObject = value.asJsObject
// get only non-optional values here
val Seq(transaction_hash, output_index, locked_satoshies, addresses, script_hex, spent) =
jsObject.getFields("transaction_hash", "output_index", "value", "addresses",
"script_hex", "spent")
println("Asset Id: " + jsObject.fields.get("asset_id"))
val assetId = jsObject.fields.get("asset_id") match {
case Some(JsString(s)) => println("S : " + s); Some(s)
case None => None
}
val assetQuantity = jsObject.fields.get("asset_quantity") match {
case Some(JsNumber(n)) => Some(n.toLong)
case None => None
}
// convert JsArray to List[ BitcoinAdress ]
val addressList = addresses match {
case ja: JsArray => {
ja.elements.toList.map(e => BitcoinAddress(e.convertTo[String]))
}
}
UnspentTXO(transaction_hash.convertTo[String], output_index.convertTo[Int],
locked_satoshies.convertTo[Long], assetId, assetQuantity,
addressList, script_hex.convertTo[String], spent.convertTo[Boolean])
最后这里是错误信息:
[info] - must create an unsigned nlocktime for all of the bitcoin in an address *** FAILED ***
[info] spray.httpx.PipelineException: Some(null) (of class scala.Some)
[info] at spray.httpx.ResponseTransformation$$anonfun$unmarshal$1.apply(ResponseTransformation.scala:36)
[info] at spray.httpx.ResponseTransformation$$anonfun$unmarshal$1.apply(ResponseTransformation.scala:31)
[info] at scala.util.Success$$anonfun$map$1.apply(Try.scala:236)
[info] at scala.util.Try$.apply(Try.scala:191)
[info] at scala.util.Success.map(Try.scala:236)
[info] at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
[info] at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
[info] at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
[info] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:67)
[info] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:82)
[info] ...
[info] Cause: scala.MatchError: Some(null) (of class scala.Some)
[info] at com.coinprism.blockchain.UnspentTXOProtocol$UnspentTXOProtocolFormat$.read(UnspentTXOProtocol.scala:30)
[info] at com.coinprism.blockchain.UnspentTXOProtocol$UnspentTXOProtocolFormat$.read(UnspentTXOProtocol.scala:21)
[info] at spray.json.JsValue.convertTo(JsValue.scala:31)
[info] at spray.json.CollectionFormats$$anon$1$$anonfun$read$1.apply(CollectionFormats.scala:28)
[info] at spray.json.CollectionFormats$$anon$1$$anonfun$read$1.apply(CollectionFormats.scala:28)
[info] at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
[info] at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
[info] at scala.collection.Iterator$class.foreach(Iterator.scala:743)
[info] at scala.collection.AbstractIterator.foreach(Iterator.scala:1195)
[info] at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
但是我收到一条错误消息,说我正在尝试将asset_id读入Some(null)
。我想用spray json将null值反序列化为本机scala类型None
?我在哪里错了?
答案 0 :(得分:0)
为什么不使用DefaultJsonProtocol进行解析而是手动执行所有操作?甚至你的协议都有关于整数值的特殊格式的一些怪癖,spray-json可以为你做。
因此,您可以定义描述模型的案例类,并使用spray中的自动json映射器:
case class SomeReply (
transaction_hash:String,
output_index:Long,
value:Long,
asset_id:Option[Long],
asset_quantity:Option[Long],
addresses:List[String],
script_hex:String,
spent:Boolean,
confirmations:Long
)
object SomeReplyProtocol extends DefaultJsonProtocol {
// custom format for (string|int) => number conversion
implicit object StringNumFormat extends RootJsonFormat[Long] {
val numberPattern = "([0-9]+)".r
def write(value:Long) = JsNumber(value)
def read(value:JsValue) = value match {
case JsString(numberPattern(number)) => number.toLong
case JsNumber(number) => number.toLong
case _ => deserializationError("Cannot deserialize StringNumber")
}
}
implicit val replyFmt = jsonFormat9(SomeReply)
}
所以你可以用这种方式使用这段代码:
object Main {
val jsonString = """{
"transaction_hash": "fbb36255453bf8ff465d9ca5c427bd0e36cc799fda090cbcd62113f1f3e97cb4",
"output_index": 0,
"value": 2000000,
"asset_id": null,
"asset_quantity": null,
"addresses": [
"1C4kYhyLftmkn48YarSoLupxHfYFo8kp64"
],
"script_hex": "76a914795efb808598d6a24d1734b929fce1d4b713215188ac",
"spent": false,
"confirmations": 72935
}""" // value is a number
val jsonStringQuirk = """{
"transaction_hash": "fbb36255453bf8ff465d9ca5c427bd0e36cc799fda090cbcd62113f1f3e97cb4",
"output_index": 0,
"value": "2000000",
"asset_id": null,
"asset_quantity": null,
"addresses": [
"1C4kYhyLftmkn48YarSoLupxHfYFo8kp64"
],
"script_hex": "76a914795efb808598d6a24d1734b929fce1d4b713215188ac",
"spent": false,
"confirmations": 72935
}""" // value is a String here!!
def main(args: Array[String]): Unit = {
import SomeReplyProtocol._
val json = jsonString.parseJson.convertTo[SomeReply]
val jsonQ = jsonStringQuirk.parseJson.convertTo[SomeReply]
println(json) // null mapped to None, yay!
println(jsonQ) // implicit string -> int conversion here
}
}