Как заставить serde десериализовать BigInt как u64? - PullRequest
0 голосов
/ 13 марта 2020

Я использую toml и num-bigint с функцией serde для десериализации следующих данных:

[[trades]]
action = "Buy"
date_time = 2019-04-15T15:36:00+01:00
fee = [1, [44000000]]
id = "#1"
price = [-1, [20154500000]]
quantity = [1, [200000000]]

Но я получаю эта ошибка:

Error: Error { inner: ErrorInner { kind: Custom, line: Some(7), col: 14, at: Some(156), message: "invalid value: integer `20154500000`, expected u32", key: ["trades", "price"] } }

Конечно, если я сделаю значение цены меньше, чем u32::MAX, программа прекрасно скомпилируется. Но я хочу использовать это высокое значение, потому что я масштабирую числа на 1e8, чтобы не иметь дело с арифметикой с плавающей точкой c.

Можно ли заставить серию десериализовать BigInt s до u64 вместо этого?

use num_bigint::BigInt;
use serde_derive::Deserialize;
use toml::from_str;
use toml::value::Datetime;

#[derive(Debug, Deserialize)]
pub struct Trade {
    pub action: String,
    pub date_time: Datetime,
    pub fee: BigInt,
    pub id: Option<String>,
    pub price: BigInt,
    pub quantity: BigInt,
}

#[derive(Debug, Deserialize)]
pub struct TradeTable {
    pub trades: Vec<Trade>,
}

fn main() {
    let trades_string: String = String::from("[[trades]]\naction = \"Buy\"\ndate_time = 2019-04-15T15:36:00+01:00\nexchange = \"Degiro\"\nfee = [1, [44000000]]\nid = \"#1\"\nprice = [-1, [20154500000]]\nquantity = [1, [200000000]]");
    let trade_table: TradeTable = from_str(&trades_string).unwrap();
    let trades: Vec<Trade> = trade_table.trades;
}

Кроме того, вот ссылка на Rust Playground . Обратите внимание, что вам нужно будет скопировать код на локальный компьютер, поскольку вам нужна функция serde из num-bigint:

Car go .toml

[dependencies.num-bigint]
version = "0.2.6"
features = ["serde"]

1 Ответ

2 голосов
/ 13 марта 2020

Как вы создали этот файл - вы сделали это путем сериализации BigInt, или вы написали его вручную?

Я написал данные вручную.

Ваши данные неверны, следующая работа:

use num_bigint::BigInt;
use std::str::FromStr;

#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
pub struct Trade {
    pub price: BigInt,
}

fn main() {
    let price = BigInt::from_str("-201545000000000").unwrap();
    let trade = Trade { price };

    let j = serde_json::to_string(&trade).unwrap();
    println!("{}", j);
    let a: Trade = serde_json::from_str(&j).unwrap();
    assert_eq!(trade, a);

    let j = toml::to_string(&trade).unwrap();
    println!("{}", j);
    let b: Trade = toml::from_str(&j).unwrap();
    assert_eq!(trade, b);
}

Вы не должны создавать это вручную.

...