【问题标题】:Posting JSON message with no key value pair Spray发布没有键值对的 JSON 消息
【发布时间】:2015-03-23 20:55:09
【问题描述】:

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

内容类型:应用程序/json “0100000001d238c42ec059b8c7747cd51debb4310108f6279d14957472822cf061a660828b000000006b483045022100d326257244e8cb86889509cf5b4717edf273d9e6e643f571c434753059eb01a902204aa761f44e89b55af0e2fa0caef580401a4ba61eebf8bc29020ce23f6fab1ee2012102661ac805eef8015c7c8d617c65ef327c4f2272fd5d9e97456a0d32d3bcf6f563ffffffff0288130000000000001976a91430a5d35558ade668b8829a2a0f60a3f10358327e88ac306f0100000000001976a914760fdb3483204406ddb73a45b20b7c9be61d0a7e88ac00000000” P>

注意这里没有键值对。我正在尝试使用“流水线”发布此内容,但我不断收到以下错误:

> 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

【问题讨论】:

    标签: scala spray spray-client


    【解决方案1】:

    让我们分解一下:

    a) 正如其他人已经评论的那样,这不是有效的 JSON,因此它将在运行时失败:

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

    b) 您不能使用编组器,因为当前 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
    

    【讨论】:

      【解决方案2】:

      仅仅因为它被花括号包围并不能使它成为有效的 json。如果您想post invalid json

      ,Spray 确实为您提供了一些选择

      您不能将 Content-Type 设为“应用程序/文本”并将msg 作为字符串发布吗?

      【讨论】:

      • 这是我试图调用的 api docs.coinprism.apiary.io/#reference/…
      • 我从使用 application/text 得到的错误信息如下 [info] - 必须向网络广播交易 *** FAILED *** [info] The future 返回了一个异常类型: spray.httpx.UnsuccessfulResponseException,带有消息:状态:415 不支持的媒体类型 [信息] 正文:{“消息”:“此资源不支持请求实体的媒体类型 'text/plain'。”}。 (TransactionBuilderTest.scala:109)
      • 您是否能够使用像Postman 这样的 REST 客户端在喷涂应用程序之外发出请求?
      • 是的,我只是尝试使用 Postman。我能够使用application/jsonContent-Type 和消息正文作为上面的字符串发送请求。我收到另一条错误消息 - 但这是我期待的错误消息 - 特别是错误消息 { "Message": "Error", "ErrorCode": "InvalidTransactionInput" }
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2019-06-12
      • 2015-10-19
      • 2023-03-17
      相关资源
      最近更新 更多