简体   繁体   English

错误:必须在此上下文中知道此值的类型(Rust)/ serde_json值

[英]error: the type of this value must be known in this context (Rust) / serde_json Value

I am using serde_json to deserialise a json document. 我正在使用serde_json反序列化json文档。 I have a function that given a string (this is the json document), will return a serde_json Value (this is an enum that represents the json type), returns an Option. 我有一个函数,给定一个字符串(这是json文档),将返回一个serde_json值(这是一个代表json类型的枚举),返回一个Option。 This value is passed around to other functions as required. 该值将根据需要传递给其他函数。

However, I realised that passing around a Value is not quite what I want, because doing this, the key is not available. 但是,我意识到传递一个值并不是我想要的,因为这样做,键不可用。

To illustrate my point, if I have a json document that looks like this: 为了说明我的观点,如果我有一个像这样的json文档:

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

"root" is a json object, "regex" is json Null and "prefixes" is a json array. “ root”是json对象,“ regex”是json Null,“ prefixes”是json数组。

Now, the json type Value is an enum with discriminators representing the json types, eg Object, Null, Array for the examples given above. 现在,json类型的Value是一个枚举类型,该标识符带有表示json类型的标识符,例如上面给出的示例的Object,Null,Array。

The serde_json crate uses std::collections::BTreeMap to represent nodes in the json document, where the String type repesents the json keys (in the above, these would be "root", "regex" and "prefixes". So passing around just references to Values is only partly helpful, I should be passing around BTreeMap instead, so that I can access the key too. serde_json板条箱使用std :: collections :: BTreeMap表示json文档中的节点,其中String类型表示json键(在上面,它们是“ root”,“ regex”和“ prefixes”。因此,传递仅仅引用Values只是部分有用,我应该改为传递BTreeMap,以便我也可以访问键。

So this is the following function that I am trying to re-write: 因此,这是我尝试重新编写的以下函数:

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
    }    
}

So I started to re-write the function but became up against the "the type of this value must be known in this context" error: 因此,我开始重新编写该函数,但遇到“在此情况下必须知道此值的类型”错误:

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
    }
}

I found other questions on stackoverflow like this one: the type of this value must be known in this context 我在stackoverflow上发现了其他类似问题: 在这种情况下必须知道该值的类型

and using this as a helper, I tried to insert the type as follows: 并将其用作帮助程序,我尝试如下插入类型:

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

which doesnt fix the issue. 这不能解决问题。 Also, tried other similar variations to no avail. 另外,尝试了其他类似的变体也无济于事。 So how do I fix this please? 那我该如何解决呢?

EDIT: 编辑:

I have another function in this app as follows: 我在此应用程序中具有另一个功能,如下所示:

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()))
}

... and this works fine. ...,这很好。 Here you can see that I can call as_object() and then obtain the key and value as a tuple pair. 在这里,您可以看到我可以调用as_object(),然后以元组对的形式获取键和值。 I don't understand why as_object is working in one case but not the other. 我不明白为什么as_object在一种情况下起作用,而在另一种情况下却不起作用。 I would like to pull out the BTreeMap and pass this around as a borrowed item. 我想拉出BTreeMap并将其作为借来的项目传递出去。

You can change the return type of your initial function and serde_json will deserialize to the appropriate object if it can: 您可以更改初始函数的返回类型,如果可以, 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()
}

Your second example won't work because you are instantiating the Value object inside the function, and then trying to return a reference to the object you just instantiated. 第二个示例将不起作用,因为您正在实例化函数内的Value对象,然后尝试返回对刚实例化的对象的引用。 This won't work because the object will go out of scope at the end of the function and the reference will then be invalid. 这将行不通,因为该对象将在函数末尾超出范围,然后引用将无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM