< 返回版块

colatea 发表于 2023-09-01 16:50

Tags:some

如题,求助大佬,咋简化一下这坨代码?

use serde_json::Value;
use anyhow::{Result, Ok, bail};


// cargo test -- --nocapture
pub struct One;

impl One {
    
    pub fn get_dad_name(s: &str) -> Result<String> {
        let value: Value = serde_json::from_str(s)?;
        
        if let Some(data) = value.get("data") {
            if let Some(family) = data.get("family") {
                println!("--- {:?}", family.get(0));
                if let Some(one) = family.get(0) {
                    println!("-- {:?}", one);
                    if let Some(name) = one.get("dad") {
                        println!("dad name: {:?}", name);
                        if let Some(name_str) = name.as_str() {
                            return Ok(name_str.to_string());
                        }
                    }
                }
            }
        }
        bail!("not found dad name".to_string())
    }
}


#[cfg(test)]
mod test {
    use super::*;
    
    #[test]
    fn test_get_dad_name() {
        let s = r#"{
            "data" : {
                "family" : [
                    { "dad" : "daye", "bady" : "2daye" }
                ]
            }
        }"#;
        
//        assert_eq!(One::get_dad_name(s).is_ok(), true)
        assert_eq!(One::get_dad_name(s).unwrap(), "daye")
    }
}

评论区

写评论
我心飞翔 2023-09-04 10:28

if let Some(name) = value.pointer("/data/family/0/dad"){ println!("name:{}", name); }

tu6ge 2023-09-03 17:10

json[“data”][“famly”][0][0]

Bai-Jinlin 2023-09-02 12:38

你是否再找 https://docs.rs/if_chain/latest/if_chain/

7sDream 2023-09-01 18:49

但是你这示例代码里不是已经用了 serde_json 和 anyhow 了……

--
👇
colatea: 就一个地方要用一下,没想又引入一个库。

--
👇
7sDream: 如果针对的就是 json 这个场景,推荐用 json pointer。其他场景就一步步用 anyhow 的 context 吧。

https://www.rustexplorer.com/b/akrr53

fakeshadow 2023-09-01 18:37
impl One {
    pub fn get_dad_name(s: &str) -> Result<String> {
        let v = serde_json::from_str::<Value>(s)?;
        v.get("data")
            .and_then(|v| v.get("family"))
            .and_then(|v| v.get(0))
            .and_then(|v| v.get("dad"))
            .map(|v| v.to_string())
            .ok_or_else(|| anyhow!("not found dad name"))
    }
}
作者 colatea 2023-09-01 18:23

就一个地方要用一下,没想又引入一个库。

--
👇
7sDream: 如果针对的就是 json 这个场景,推荐用 json pointer。其他场景就一步步用 anyhow 的 context 吧。

https://www.rustexplorer.com/b/akrr53

作者 colatea 2023-09-01 18:22

这个可以的。感谢

--
👇
dierbei: 可以试试这样行不行

        if let Some(name) = value
            .get("data")
            .and_then(|data| data.get("family"))
            .and_then(|family| family.get(0))
            .and_then(|one| one.get("dad"))
            .and_then(|name| name.as_str())
        {
            return Ok(name.to_string());
        }
any35 2023-09-01 17:28

啊?! 这....

pub fn get_dad_name(s: &str) -> Option<String> {
    let value: Value = serde_json::from_str(s).ok()?;
    
    let name_str = value.get("data")?
        .get("family")?
        .get(0)?
        .get("dad")?
        .as_str()?;

    Some(name_str.to_string())
}
7sDream 2023-09-01 17:19

如果针对的就是 json 这个场景,推荐用 json pointer。其他场景就一步步用 anyhow 的 context 吧。

https://www.rustexplorer.com/b/akrr53

dierbei 2023-09-01 16:54

可以试试这样行不行

        if let Some(name) = value
            .get("data")
            .and_then(|data| data.get("family"))
            .and_then(|family| family.get(0))
            .and_then(|one| one.get("dad"))
            .and_then(|name| name.as_str())
        {
            return Ok(name.to_string());
        }
1 共 10 条评论, 1 页