2015-03-23 8 views
1

Вот пример того, что я пытаюсь разместить на веб-службы:Проводка JSON сообщения без пары ключей значение Spray

Content-Type: применение/JSon «0100000001d238c42ec059b8c7747cd51debb4310108f6279d14957472822cf061a660828b000000006b483045022100d326257244e8cb86889509cf5b4717edf273d9e6e643f571c434753059eb01a902204aa761f44e89b55af0e2fa0caef580401a4ba61eebf8bc29020ce23f6fab1ee2012102661ac805eef8015c7c8d617c65ef327c4f2272fd5d9e97456a0d32d3bcf6f563ffffffff0288130000000000001976a91430a5d35558ade668b8829a2a0f60a3f10358327e88ac306f0100000000001976a914760fdb3483204406ddb73a45b20b7c9be61d0a7e88ac00000000»

Обратите внимание, что здесь нет пары ключ-значение. Я пытаюсь использовать «конвейерный» для 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)) 

Что я делаю неправильно?

EDIT:

API-интерфейс, что я пытаюсь позвонить:

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

ответ

1

Давайте разбить его:

а) Как и другие уже прокомментировали это не является действительным JSON, так она не будет выполнена во время выполнения:

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

б) Вы не можете использовать marshallers, потому что в настоящее время распылять (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] 

Вы должны понимать, что спрей обрабатывает заголовок 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 
0

Просто потому, что она окружена фигурными скобками, не делает его действительным JSON. Спрей дает вам несколько вариантов, если вы хотите post invalid json

Не можете ли вы сделать «приложение/текст» Content-Type и отправить msg в виде строки?

+0

Вот апи, что я пытаюсь вызвать http://docs.coinprism.apiary.io/#reference/transaction-signing- and-broadcasting/push-a-signed-raw-transaction-to-the-network/post? console = 1 –

+0

сообщение об ошибке, которое я получаю от использования 'application/text', является следующим [info] - должно транслировать транзакцию на сеть *** FAILED *** [info] В будущем возвращается исключение типа: spray.httpx.UnsuccessfulResponseException, с сообщением: Статус: 415 Неподдерживаемый тип носителя [info] Тело: {"Сообщение": "Запрос тип медиаресурса 'text/plain' равен n ot поддерживается для этого ресурса. "}. (TransactionBuilderTest.scala: 109) –

+0

Вы можете сделать запрос за пределами своего приложения для распыления клиентом REST, например [Почтальон] (https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm ? = гл ен)? – Gangstead