发布没有键值对Spray的JSON消息

时间:2015-03-23 20:55:09

标签: scala spray spray-client

以下是我尝试发布到网络服务的示例:

  

Content-Type:application / json   " 0100000001d238c42ec059b8c7747cd51debb4310108f6279d14957472822cf061a660828b000000006b483045022100d326257244e8cb86889509cf5b4717edf273d9e6e643f571c434753059eb01a902204aa761f44e89b55af0e2fa0caef580401a4ba61eebf8bc29020ce23f6fab1ee2012102661ac805eef8015c7c8d617c65ef327c4f2272fd5d9e97456a0d32d3bcf6f563ffffffff0288130000000000001976a91430a5d35558ade668b8829a2a0f60a3f10358327e88ac306f0100000000001976a914760fdb3483204406ddb73a45b20b7c9be61d0a7e88ac00000000"

请注意,此处没有键值对。我正在尝试使用“流水线”#39; POST这个,但我继续收到以下错误:

> test
[info] Compiling 1 Scala source to /home/chris/dev/coinprism-api/target/scala-2.11/classes...
[error] /home/chris/dev/coinprism-api/src/main/scala/com/coinprism/transaction/TransactionBuilder.scala:102: could not find implicit value for evidence parameter of type spray.httpx.marshalling.Marshaller[spray.json.JsObject]
[error]     pipeline(Post(host + version + sendrawtransaction, msg))

以下是我尝试使用的代码:

import TransactionHashFormat._
import DefaultJsonProtocol._
val msg = ("""{"0100000001d238c42ec059b8c7747cd51debb4310108f6279d14957472822cf061a660828b000000006b483045022100d326257244e8cb86889509cf5b4717edf273d9e6e643f571c434753059eb01a902204aa761f44e89b55af0e2fa0caef580401a4ba61eebf8bc29020ce23f6fab1ee2012102661ac805eef8015c7c8d617c65ef327c4f2272fd5d9e97456a0d32d3bcf6f563ffffffff0288130000000000001976a91430a5d35558ade668b8829a2a0f60a3f10358327e88ac306f0100000000001976a914760fdb3483204406ddb73a45b20b7c9be61d0a7e88ac00000000"}""").asJson.asJsObject
val pipeline: HttpRequest => Future[TransactionHash] =
  addHeader("Content-Type" , "application/json") ~> sendReceive ~> unmarshal[TransactionHash]
pipeline(Post(host + version + sendrawtransaction, msg))

我做错了什么?

编辑:

我想要调用的API:

http://docs.coinprism.apiary.io/#reference/transaction-signing-and-broadcasting/push-a-signed-raw-transaction-to-the-network/post?console=1

2 个答案:

答案 0 :(得分:1)

让我们分解一下:

a)正如其他人已经评论过这不是有效的JSON所以它会在运行时失败:

val msg = ("""{"0100000001d238c42ec059b8c7747cd51debb4310108f6279d14957472822cf061a660828b000000006b483045022100d326257244e8cb86889509cf5b4717edf273d9e6e643f571c434753059eb01a902204aa761f44e89b55af0e2fa0caef580401a4ba61eebf8bc29020ce23f6fab1ee2012102661ac805eef8015c7c8d617c65ef327c4f2272fd5d9e97456a0d32d3bcf6f563ffffffff0288130000000000001976a91430a5d35558ade668b8829a2a0f60a3f10358327e88ac306f0100000000001976a914760fdb3483204406ddb73a45b20b7c9be61d0a7e88ac00000000"}""").asJson.asJsObject

b)你不能使用marshallers,因为当前的spray(1.3.2)只允许编组JSON对象和数组。这是前JSON规范(RFC 4627)的要求,但是这个要求已经被新的RFC 7159取消了。我创建了一张票,以便将来修复这个https://github.com/spray/spray/issues/1034。但是,您要定位的API需要双引号JSON字符串。

c)这意味着您需要在这种情况下不能使用编组(即将Scala值自动转换为HTTP消息)。这不是您自己创建消息所需的特殊问题。这样的事情应该有效:

val pipeline = sendReceive
val hash: String = "0100000001d238c42ec059b8c7747cd51debb4310108f6279d14957472822cf061a660828b000000006b483045022100d326257244e8cb86889509cf5b4717edf273d9e6e643f571c434753059eb01a902204aa761f44e89b55af0e2fa0caef580401a4ba61eebf8bc29020ce23f6fab1ee2012102661ac805eef8015c7c8d617c65ef327c4f2272fd5d9e97456a0d32d3bcf6f563ffffffff0288130000000000001976a91430a5d35558ade668b8829a2a0f60a3f10358327e88ac306f0100000000001976a914760fdb3483204406ddb73a45b20b7c9be61d0a7e88ac00000000"
val msg: String = "\"" + hash + "\""
val request = Post(host + version + sendrawtransaction, HttpEntity(ContentTypes.`application/json`, msg))

// run request
pipeline(request) // receive result as Future[HttpResponse]

您需要了解spray特别处理Content-Type标头:它不表示为普通标头,但它被建模为HttpEntity的一部分。

不幸的是,unmarshal由于b)中解释的原因不起作用,因此您需要自己提取值。

你应该能够大致这样做:

def extractJsonStringResult(res: HttpResponse): String = {
  // TODO: check status code
  import spray.json._
  res.entity.asString(HttpCharsets.`UTF-8`).parseJson match {
    case JsString(string) => string
    case _ => ??? // TODO: fail
  }
}
val pipeline = sendReceive ~> extractJsonStringResult

答案 1 :(得分:0)

仅仅因为它被花括号括起来并没有使它成为有效的json。如果你想要post invalid json

,Spray会给你一些选择

你不能制作内容类型"应用程序/文本"并将msg发布为字符串?