2017-02-20 13 views
-1

У меня есть тесты, и мне нужно отправить данные JSON на мой сервер. У меня есть следующий тест:Как преобразовать структуру или JSON в необработанную строку?

extern crate hyper; 
extern crate rustc_serialize; 

use std::io::Read; 
use hyper::*; 

#[derive(RustcDecodable, RustcEncodable)] 
struct LegacyJsonRequest { 
    jsonrpc: String, 
    method: String, 
    params: String, 
    id: i32, 
    auth: String, 
} 

#[test] 
fn apiinfo_jsonrpc_tests() { 
    let client = Client::new(); 

    let url = "http://localhost:6767/api_jsonrpc.php"; 

    let mut http_reader = header::Headers::new(); 
    http_reader.set_raw("Content-Type", vec![b"application/json".to_vec()]); 

    //TODO: How to use a struct and 'export' it to a raw string literal??? 
    let request_data = LegacyJsonRequest { 
     jsonrpc: "2.0".to_string(), 
     method: "apiinfo.version".to_string(), 
     params: "[]".to_string(), 
     auth: "[]".to_string(), 
     id: 1, 
    }; 

    let encoded_request = rustc_serialize::json::encode(&request_data).unwrap(); 

    let mut response = client.post(url) 
     .body(encoded_request) 
     .send() 
     .unwrap(); 

} 

С помощью этого кода, возвращается следующее сообщение об ошибке:

error[E0277]: the trait bound `hyper::client::Body<'_>: std::convert::From<std::string::String>` is not satisfied 

Если я уронить структура и JSON закодированный код и создать простую сырец строкового литерала и ссылки он по методу тела, он работает. Пример:

extern crate hyper; 
extern crate rustc_serialize; 

use std::io::Read; 
use hyper::*; 

#[derive(RustcDecodable, RustcEncodable)] 
struct LegacyJsonRequest { 
    jsonrpc: String, 
    method: String, 
    params: String, 
    id: i32, 
    auth: String, 
} 

#[test] 
fn apiinfo_jsonrpc_tests() { 
    let client = Client::new(); 

    let url = "http://localhost:6767/api_jsonrpc.php"; 

    let mut http_reader = header::Headers::new(); 
    http_reader.set_raw("Content-Type", vec![b"application/json".to_vec()]); 

    let request_data = 
     r#"{"jsonrpc":"2.0", "method": "apiinfo.version", "params": {}, "auth": {}, "id": "1"}"#; 

    let mut response = client.post(url) 
     .body(request_data) 
     .send() 
     .unwrap(); 

} 

Итак: Как я могу конвертировать мою структуру или JSON в сырой строки?

Я знаю, что ошибка E0277 связана с реализацией признака «Hyper :: client :: Body < '_>», но посмотрите, это не вопрос; возникает вопрос: как преобразовать структуру или JSON в необработанную строку, не более того. Благодарю.

+0

Я предлагаю вам продолжить исследование того, что означает это сообщение об ошибке. – Shepmaster

+0

Я только что добавил более полные примеры. Если я могу преобразовать объект JSON или Struct в необработанную строку, тогда мне не нужно реализовывать черту для гипер :: client :: Body <'_>. Речь идет о конверсии. –

ответ

2

Я знаю, что E0277 ошибки о реализации признака для «Hyper :: клиента :: Body <«_>», но посмотрите, это не вопрос; возникает вопрос: как преобразовать структуру или JSON в необработанную строку, не более того.

100% невозможно для преобразования в необработанную строку.

Вы видите, что «необработанные строки» не существуют после разбора исходного кода - это всего лишь тщеславие исходного кода. Нет способа конвертировать что-нибудь в необработанную строку, потому что она не существует для преобразования в.

Все, что существует, это струнные срезы (&str) и принадлежащие им строки (String).

Это решает вопрос ОП, не более того, по запросу. Любой, кто заинтересован в решении основной проблемы, может продолжить чтение.


Проверка documentation for RequestBuilder::body, вы можете увидеть, что он принимает любой тип, который может быть преобразован в Body:

impl<'a> RequestBuilder<'a> { 
    fn body<B: Into<Body<'a>>>(self, body: B) -> RequestBuilder<'a>; 
} 

Если вы затем рассмотреть documentation for Body, вы увидите, что существуют реализации From существуют это:

impl<'a, R: Read> From<&'a mut R> for Body<'a> { 
    fn from(r: &'a mut R) -> Body<'a>; 
} 

в сочетании с осознанием того, что From implies Into, вы знаете, ТНА t вы можете передать все, что реализует Read, до body.На самом деле, компилятор говорит вам об этом в сообщении об ошибке:

error[E0277]: the trait bound `hyper::client::Body<'_>: std::convert::From<std::string::String>` is not satisfied 
    --> src/main.rs:37:10 
    | 
37 |   .body(encoded_request) 
    |   ^^^^ the trait `std::convert::From<std::string::String>` is not implemented for `hyper::client::Body<'_>` 
    | 
    = help: the following implementations were found: 
    = help: <hyper::client::Body<'a> as std::convert::From<&'a mut R>> 
    = note: required because of the requirements on the impl of `std::convert::Into<hyper::client::Body<'_>>` for `std::string::String` 

Это проблема - есть на самом деле более способы преобразования в Body, и документация не показать им ! Покидаем the source, вы можете увидеть:

impl<'a> Into<Body<'a>> for &'a str { 
    #[inline] 
    fn into(self) -> Body<'a> { 
     self.as_bytes().into() 
    } 
} 

impl<'a> Into<Body<'a>> for &'a String { 
    #[inline] 
    fn into(self) -> Body<'a> { 
     self.as_bytes().into() 
    } 
} 

Это означает, что вы можете передать ссылку на строку, которая затем будет превращена в Body, так же, как vitalyd guessed:

let mut response = client.post(url) 
    .body(&encoded_request) 
    .send() 
    .unwrap(); 

Я собираюсь посмотреть, является ли это уже зарегистрированной проблемой или нет, так как это кажется неправильным.

+0

Удивительный ответ. Я попробую это сегодня вечером. До сих пор для меня Rust не имеет высокой кривой обучения; вместо этого он решает проблемы простым способом, который заставляет нас думать о новых возможностях. –