【问题标题】:error: the type of this value must be known in this context (Rust) / serde_json Value错误:此值的类型必须在此上下文中已知(Rust)/serde_json 值
【发布时间】:2016-05-25 14:16:39
【问题描述】:

我正在使用 serde_json 反序列化 json 文档。我有一个函数,给定一个字符串(这是 json 文档),将返回一个 serde_json 值(这是一个表示 json 类型的枚举),返回一个选项。 该值会根据需要传递给其他函数。

但是,我意识到传递值并不是我想要的,因为这样做,密钥不可用。

为了说明我的观点,如果我有一个如下所示的 json 文档:

{
  "root" : {
    "regex" : null,
    "prefixes" : [ "a_", "b_" ]
  }
}

“root”为json对象,“regex”为json Null,“prefixes”为json数组。

现在,json 类型 Value 是一个枚举,带有表示 json 类型的鉴别符,例如上面给出的示例中的 Object、Null、Array。

serde_json crate 使用 std::collections::BTreeMap 来表示 json 文档中的节点,其中 String 类型表示 json 键(在上面,这些将是“root”、“regex”和“prefixes”。所以只传递对 Values 的引用只是部分有用,我应该传递 BTreeMap 来代替,这样我也可以访问密钥。

所以这是我要重写的以下函数:

fn get_json_content(content_s : &str) -> Option<Value> {
    // instead of returning a value, we need to return a BTreeMap, so we can get the
    // key and the value.
    println!("===>>> json_content obtained: {}", content_s);

    match serde_json::from_str(content_s) { // -> Result<Value>
        Ok(some_value) => Some(some_value),
        Err(_) => None
    }    
}

所以我开始重新编写函数,但遇到了“在这个上下文中必须知道这个值的类型”错误:

fn get_json_content_as_btreemap<'a>(content_s : &str) -> Option<&'a BTreeMap<String, Value>> {
    match serde_json::from_str(content_s) { // -> Result<Value>
        Ok(some) => {
            // I expect the type of key_value_pair to be BTreeMap<String, Value>>
            // (but I may be wrong!)
            let key_value_pair = some.as_object().unwrap(); // Error here

        },
        Err(_) => None
    }
}

我在 stackoverflow 上发现了其他类似的问题: the type of this value must be known in this context

并使用它作为助手,我尝试按如下方式插入类型:

let key_value_pair = some.as_object::<BTreeMap<_, _>>().unwrap();

这不能解决问题。此外,尝试了其他类似的变化无济于事。那请问我该如何解决呢?

编辑:

我在这个应用中还有一个功能如下:

fn get_root_value<'a>(json_documemt : &'a Value) -> Result<&'a Value, JsonErrorCode> {
    if json_documemt.is_object() {
        for (k, v) in json_documemt.as_object().unwrap().iter() {
            if k == "root" {
                println!("found root: {}",  k);

                return Ok(v)
            }
        }

        return Err(JsonErrorCode::Custom("Failed to find root node".to_string()))
    }

    Err(JsonErrorCode::Custom("Not an object".to_string()))
}

... 这很好用。在这里你可以看到我可以调用 as_object() ,然后以元组对的形式获取键和值。我不明白为什么 as_object 在一种情况下有效,而在另一种情况下无效。我想拉出 BTreeMap 并将其作为借来的项目传递。

【问题讨论】:

    标签: json compiler-errors rust serde


    【解决方案1】:

    您可以更改初始函数的返回类型,如果可以,serde_json 将反序列化为适当的对象:

    fn get_json_content(content_s : &str) -> Option<BTreeMap<String, Value>> {
        // instead of returning a value, we need to return a BTreeMap, so we can get the
        // key and the value.
        println!("===>>> json_content obtained: {}", content_s);
    
        match serde_json::from_str(content_s) { // -> Result<Value>
            Ok(some_value) => Some(some_value),
            Err(_) => None
        }    
        // Note: this match statement can be rewritten as
        // serde_json::from_str(content_s).ok()
    }
    

    您的第二个示例不起作用,因为您在函数内实例化 Value 对象,然后尝试返回对您刚刚实例化的对象的引用。这不起作用,因为对象将在函数结束时超出范围,然后引用将无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 2022-11-21
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      相关资源
      最近更新 更多