Есть ли способ преобразовать карту Серде в значение?

Согласно спецификации Serde, Object / Map<String, Value> - это Value:

pub enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

Но когда я компилирую этот код:

extern crate serde;
#[macro_use]
extern crate serde_json;

#[derive(Debug)]
struct Wrapper {
    ok: bool,
    data: Option<serde_json::Value>,
}

impl Wrapper {
    fn ok() -> Wrapper {
        Wrapper {
            ok: true,
            data: None,
        }
    }

    pub fn data(&mut self, data: serde_json::Value) -> &mut Wrapper {
        self.data = Some(data);
        self
    }

    pub fn finalize(self) -> Wrapper {
        self
    }
}

trait IsValidWrapper {
    fn is_valid_wrapper(&self) -> bool;
}

impl IsValidWrapper for serde_json::Map<std::string::String, serde_json::Value> {
    fn is_valid_wrapper(&self) -> bool {
        self["ok"].as_bool().unwrap_or(false)
    }
}

fn main() {
    let json = json!({
          "name": "John Doe",
          "age": 43,
          "phones": [
            "+44 1234567",
            "+44 2345678"
          ]
        });

    let converted_json: Wrapper = json
        .as_object()
        .map_or_else(
            || Err(json),
            |obj| {
                if obj.is_valid_wrapper() {
                    Ok(Wrapper::ok().data(obj["data"].clone()).finalize())
                } else {
                    Err(*obj as serde_json::Value)
                }
            },
        )
        .unwrap_or_else(|data| Wrapper::ok().data(data.clone()).finalize());
    println!(
        "org json = {:?} => converted json = {:?}",
        json, converted_json
    );
}

Я получаю такую ​​ошибку:

error[E0605]: non-primitive cast: `serde_json::Map<std::string::String, serde_json::Value>` as `serde_json::Value`
  --> src/main.rs:60:25
   |
60 |                     Err(*obj as serde_json::Value)
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

Есть ли способ превратить Map в Value?


person Boris    schedule 15.05.2017    source источник
comment
Map не Value, вы пробовали Err(Value::Object(obj))?   -  person tafia    schedule 15.05.2017
comment
@LukasKalbertodt Я отредактировал свой первоначальный пост в соответствии с просьбой   -  person Boris    schedule 15.05.2017
comment
@tafia вроде работает. У меня есть еще несколько ошибок компилятора, которые я рассмотрю, но, по крайней мере, проблема с компилятором исчезла. Действительно, карта - это не значение, а значение :: объект; спасибо, что указали на это   -  person Boris    schedule 15.05.2017


Ответы (1)


an Object / Map<String, Value> is a Value

Нет это не так. Value - это тип. Map<String, Value> - это тип. Value::Object - это вариант перечисления, который не является отдельным типом. В этом случае Value::Object содержит другое значение типа Map<String, Value>. Вы должны заключить значение в вариант, чтобы преобразовать тип:

Err(serde_json::Value::Object(obj))

Это приведет вас к проблеме:

error[E0308]: mismatched types
  --> src/main.rs:57:55
   |
57 |                         Err(serde_json::Value::Object(obj))
   |                                                       ^^^ expected struct `serde_json::Map`, found reference
   |
   = note: expected type `serde_json::Map<std::string::String, serde_json::Value>`
              found type `&serde_json::Map<std::string::String, serde_json::Value>`

as_object возвращает ссылку на содержащийся объект (если он присутствует), а не само значение. На данный момент вам нужно match:

let converted_json = match json {
    serde_json::Value::Object(obj) => {}
    _ => {}
};

Что-то вроде этого:

let converted_json = match json {
    serde_json::Value::Object(obj) => {
        if obj.is_valid_wrapper() {
            let mut w = Wrapper::ok();
            w.data(obj["data"].clone());
            Ok(w.finalize())
        } else {
            Err(serde_json::Value::Object(obj))
        }
    }
    other => Err(other),
};
person Shepmaster    schedule 15.05.2017