8个版本 (稳定版)

1.1.3 2024年1月1日
1.1.2 2023年12月30日
0.1.0 2023年12月8日

#888解析器实现

Download history 18/week @ 2024-03-11 15/week @ 2024-03-25 13/week @ 2024-04-01 6/week @ 2024-05-13 19/week @ 2024-05-20 20/week @ 2024-05-27 19/week @ 2024-06-03 24/week @ 2024-06-10 10/week @ 2024-06-17 21/week @ 2024-06-24

每月75次下载
5 crates中使用

GPL-2.0-or-later

53KB
1K SLoC

WJP - Wizards JSON解析器

一个库,可以将原始字符串解析为可操作的类型,反之亦然。

Latest version Documentation Reliability Rating Quality Gate Status Technical Debt

文档

基本用法

将库导入到Cargo.toml中

[dependencies]
wjp = "1.1.3"

// Example Struct to show how this library works
#[derive(Debug)]
struct Example {
    code: f32,
    messages: Vec<String>,
    opt: Option<bool>,
}

// Implementing the Serialize Trait allows you to call the .json() method on your struct
impl Serialize for Example {
    fn serialize(&self) -> Values {
        // The map!() macro is a helper to create a hashmap from the given values
        Values::Struct(map!(
            // Many Data Structures and Types already have Serialize implemented
            ("code", self.code.serialize()),
            ("messages", self.messages.serialize()),
            ("opt", self.opt.serialize())
        ))
    }
}

// Implementing the TryFrom<Values> Trait allows you to deserialize a JSON String into your struct
impl TryFrom<Values> for Example {
    // We advise on using the ParseError because many helper methods build on this error
    type Error = ParseError;
    fn try_from(value: Values) -> Result<Self, Self::Error> {
        // Now you just need to get your struct / array and get the keys with their appropriate values
        let mut struc = value.get_struct().ok_or(ParseError::new())?;
        let code = struc.map_val("code", f32::try_from)?;
        // Many Data Structures and Types already have TryFrom<Values> implemented
        let messages = struc.map_val("messages", Vec::try_from)?;
        // This is sadly not the case for Option<T> where your need to find out what the type of T is and parse that
        let opt = struc.map_opt_val("opt", |val| val.get_bool())?;
        Ok(Self {
            opt,
            messages,
            code,
        })
    }
}

pub fn main() {
    let example = Example {
        code: 123.0,
        messages: vec!["Important".to_string(), "Message".to_string()],
        opt: None,
    };
    // After implementing these two traits you can call the .json() method to serialize your struct
    let json = example.json();
    println!("{}", json);
    // And the <Your Type>::deserialize(&str/String) to deserialize it 
    let back = Example::deserialize(json);
    println!("{:?}", back);
}

上面示例的输出

{"opt":null,"code":123,"messages":["Important","Message"]}

Ok(Example { code: 123.0, messages: ["Important", "Message"], opt: None })

解释

JSON是一种轻量级、基于文本的、与语言无关的数据交换格式。尽管它是语言无关的,但它并不是针对Rust语言优化的。

示例JSON
{
  "type": "error",
  "message": "A really bad Error occurred",
  "code": 444
}

键值对每次可能处于不同的位置
{
  "code": 444,
  "message": "A really bad Error occurred",
  "type": "error"
}

这目前也是这个库的情况,因为它使用HashMap在新的位置分配键值对并从不同位置交付它们


键值对可能不存在、值为null或具有不同类型
{
  "code": null,
  "type": 123.23
}

这被支持,但会使解析部分更加困难,因此使用这个库的用户需要为它们想要解析的每个结构体实现From<Values>Serialize


JSON支持IEEE 754标准存储数字
{
  "plus": 1,
  "minus": -1,
  "minus-zero": -0,
  "exponent": 10E10,
  "minus-exponent": 10e-10,
  "decimal-point": 1.2,
  "decimal-point-exponent": 1.23E-10
}

这被支持,但只是使用了f64::from_str(),它应该支持所有这些情况


JSON也支持UTF-8编码
{
  "text": "\u1234",
  "info": "  ^ This is not supported "
}

这个库不支持转义字符,并且不建议使用转义字符


JSON在数组内部也支持不同类型
[
  true,
  false,
  null,
  1.23,
  false
]

这被支持,但用户需要弄清楚如何处理可以包含不同类型的Vec<Values>

无运行时依赖