将Vec >反序列化为Vec 直接

问题描述 投票:0回答:1

我得到了一种数据格式,其中包括一系列对象,每个对象都有一个命名字段value。反序列化时能否删除此间接层?

反序列化时,自然表示为

/// Each record has it's own `{ value: ... }` object
#[derive(serde::Deserialize)]
struct Foobar<T> {
    value: T,
}

/// The naive representation, via `Foobar`...
#[derive(serde::Deserialize)]
struct FoobarContainer {
    values: Vec<Foobar<T>>,
}

虽然Foobar除了T之外没有增加任何额外成本,但我想在类型级别上删除此间接层:

#[derive(serde::Deserialize)]
struct FoobarContainer {
    values: Vec<T>,
}

Foobar是否仍可以通过反序列化从FoobarContainer中删除?

rust serde
1个回答
0
投票

在一般情况下,没有简单的方法可以进行这种转换。为此,请查看以下现有答案:

但是,就您而言,您说:

仅具有一个命名字段值的对象

您已经确定了关键要求:

虽然Foobar除了T之外没有增加任何额外成本,但>

这意味着您可以使Foobar具有transparent

表示形式,并使用unsafe Rust在类型之间进行转换:
struct FoobarContainer<T> {
    values: Vec<T>,
}

#[derive(serde::Deserialize)]
#[repr(transparent)]
struct Foobar<T> {
    value: T,
}

impl<'de, T> serde::Deserialize<'de> for FoobarContainer<T>
where
    T: serde::Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let v: Vec<Foobar<T>> = serde::Deserialize::deserialize(deserializer)?;

        // I copied this from Stack Overflow without reading the surrounding
        // text that describes why this is actually safe.
        let values = unsafe { std::mem::transmute(v) };

        Ok(FoobarContainer { values })
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.