最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

deserialization - Force Rust serde to deserialize JSON Number to u16 - Stack Overflow

programmeradmin3浏览0评论

How can I force serde to parse a JSON Number as a Rust u16 type?

Below I parse a JSON file. json_data is of type Value. This only has a as_u64() method, no as_u16(). As a result I first have to parse the JSON Number as a u64, then try and parse that as u16. This seems fairly convoluted. Is there some way I can force serde_json to parse this value as a u16 to avoid this?

(As a side note, the JSON data has already been validated using a JSON schema, which checks the value of x is within the bounds of u16).

$ cat test.json
{
    "x": 100
}
use serde_json::Value;
use std::fs::File;
use std::io::BufReader;

pub struct Test {
    pub x: u16,
}

fn main() {
    let filename = "test.json";
    let file =
        File::open(filename).unwrap_or_else(|e| panic!("Unable to open file {}: {}", filename, e));
    let reader = BufReader::new(file);
    let json_data: Value = serde_json::from_reader(reader)
        .unwrap_or_else(|e| panic!("Unable to parse JSON file {}: {}", filename, e));

    assert!(json_data["x"].is_u64());

    let mut t = Test { x: 5 };

    if json_data["x"].is_u64() {
        let _new_x: u64 = json_data["x"].as_u64().expect("Unable to parse x");
        t.x = u16::try_from(_new_x).expect("Unable to convert x to u16");
    }
}

How can I force serde to parse a JSON Number as a Rust u16 type?

Below I parse a JSON file. json_data is of type Value. This only has a as_u64() method, no as_u16(). As a result I first have to parse the JSON Number as a u64, then try and parse that as u16. This seems fairly convoluted. Is there some way I can force serde_json to parse this value as a u16 to avoid this?

(As a side note, the JSON data has already been validated using a JSON schema, which checks the value of x is within the bounds of u16).

$ cat test.json
{
    "x": 100
}
use serde_json::Value;
use std::fs::File;
use std::io::BufReader;

pub struct Test {
    pub x: u16,
}

fn main() {
    let filename = "test.json";
    let file =
        File::open(filename).unwrap_or_else(|e| panic!("Unable to open file {}: {}", filename, e));
    let reader = BufReader::new(file);
    let json_data: Value = serde_json::from_reader(reader)
        .unwrap_or_else(|e| panic!("Unable to parse JSON file {}: {}", filename, e));

    assert!(json_data["x"].is_u64());

    let mut t = Test { x: 5 };

    if json_data["x"].is_u64() {
        let _new_x: u64 = json_data["x"].as_u64().expect("Unable to parse x");
        t.x = u16::try_from(_new_x).expect("Unable to convert x to u16");
    }
}
Share Improve this question asked Mar 14 at 17:00 BaldrickBaldrick 11k21 gold badges78 silver badges93 bronze badges 0
Add a comment  | 

1 Answer 1

Reset to default 5

Don't use the raw serde_json::Value type for this usecase.

While it is possible, it is not what serde is intended for; instead, serde is meant to deserialize directly into your struct.

The magic here is adding a #[derive(Deserialize)] to your struct. Be aware that you need to activate the derive feature of serde for this.

Like so:

use serde::Deserialize;
use std::fs::File;
use std::io::BufReader;

#[derive(Debug, Deserialize)]
pub struct Test {
    pub x: u16,
}

fn main() {
    let filename = "test.json";
    let file =
        File::open(filename).unwrap_or_else(|e| panic!("Unable to open file {}: {}", filename, e));
    let reader = BufReader::new(file);
    let json_data: Test = serde_json::from_reader(reader)
        .unwrap_or_else(|e| panic!("Unable to parse JSON file {}: {}", filename, e));

    println!("{:?}", json_data)
}
Test { x: 100 }

If you now change the test.json to:

{
    "x": 123456
}

You get:

thread 'main' panicked at src\main.rs:16:29:
Unable to parse JSON file test.json: invalid value: integer `123456`, expected u16 at line 2 column 16
发布评论

评论列表(0)

  1. 暂无评论