如何将`serde_json::Value`在Rust中转换为`prost_types::Struct`?

huangapple go评论131阅读模式
英文:

How to convert a `serde_json::Value ` to a `prost_types::Struct` in Rust?

问题

fn to_struct(json: serde_json::Value) -> prost_types::Struct {
  // 如何实现它?
}

有没有用于此目的的 crate?

英文:
fn to_struct(json: serde_json::Value) -> prost_types::Struct {
  // How to implement it?
}

Is there any crate to do it?

答案1

得分: 1

以下是您要求的代码部分的翻译:

这不一定需要使用 crate。但是您的类型混合了:并非所有 `serde_json::Value` 都可以转换为 `prost_type::Struct`,因为 `serde_json::Value` 也可以是列表、字符串、布尔值、数字或空值。如果您确实想要转换为结构体,您需要从 `serde_json::Map` 开始:

fn to_struct(json: serde_json::Map<String, serde_json::Value>) -> prost_types::Struct {
    prost_types::Struct {
        fields: json
            .into_iter()
            .map(|(k, v)| (k, serde_json_to_prost(v)))
            .collect(),
    }
}

但很可能您只需要以下部分:

fn serde_json_to_prost(json: serde_json::Value) -> prost_types::Value {
    use prost_types::value::Kind::*;
    use serde_json::Value::*;

    prost_types::Value {
        kind: Some(match json {
            Null => NullValue(0 /* 什么? */),
            Bool(v) => BoolValue(v),
            Number(n) => NumberValue(n.as_f64().expect("无法表示为非 f64 类型的数字")),
            String(s) => StringValue(s),
            Array(v) => ListValue(prost_types::ListValue {
                values: v.into_iter().map(serde_json_to_prost).collect(),
            }),
            Object(v) => StructValue(to_struct(v)),
        }),
    }
}

请注意,这是 Rust 代码,与中文翻译的一部分,用于解释代码的目的和功能。

英文:

This is not necessarily something you need a crate for. You do however have your types mixed: Not all serde_json::Values can be converted to a prost_type::Struct, as serde_json::Values can also be lists or strings or bools or numbers or null. If you do want to convert to a struct, you'll need to start from a serde_json::Map:

fn to_struct(json: serde_json::Map&lt;String, serde_json::Value&gt;) -&gt; prost_types::Struct {
    prost_types::Struct {
        fields: json
            .into_iter()
            .map(|(k, v)| (k, serde_json_to_prost(v)))
            .collect(),
    }
}

Likely though, you only need the following

fn serde_json_to_prost(json: serde_json::Value) -&gt; prost_types::Value {
    use prost_types::value::Kind::*;
    use serde_json::Value::*;
    prost_types::Value {
        kind: Some(match json {
            Null =&gt; NullValue(0 /* wat? */),
            Bool(v) =&gt; BoolValue(v),
            Number(n) =&gt; NumberValue(n.as_f64().expect(&quot;Non-f64-representable number&quot;)),
            String(s) =&gt; StringValue(s),
            Array(v) =&gt; ListValue(prost_types::ListValue {
                values: v.into_iter().map(serde_json_to_prost).collect(),
            }),
            Object(v) =&gt; StructValue(to_struct(v)),
        }),
    }
}

Rustexplorer

答案2

得分: 0

https://crates.io/crates/prost-wkt-types 可以生成 prost_wkt_types::Struct,它支持 Deserialize trait。

英文:

https://crates.io/crates/prost-wkt-types can generate prost_wkt_types::Struct, which supports Deserialize trait.

答案3

得分: 0

在@Caesar的回答基础上,我只想展示如何在serde_json::Valueprost_types::Value之间来回转换的示例代码:

fn to_struct(json: serde_json::Map<String, serde_json::Value>) -> prost_types::Struct {
    prost_types::Struct {
        fields: json
            .into_iter()
            .map(|(k, v)| (k, serde_json_to_prost(v)))
            .collect(),
    }
}

fn serde_json_to_prost(json: serde_json::Value) -> prost_types::Value {
    use prost_types::value::Kind::*;
    use serde_json::Value::*;
    prost_types::Value {
        kind: Some(match json {
            Null => NullValue(0 /* wat? */),
            Bool(v) => BoolValue(v),
            Number(n) => NumberValue(n.as_f64().expect("Non-f64-representable number")),
            String(s) => StringValue(s),
            Array(v) => ListValue(prost_types::ListValue {
                values: v.into_iter().map(serde_json_to_prost).collect(),
            }),
            Object(v) => StructValue(to_struct(v)),
        }),
    }
}

fn prost_to_serde_json(x: prost_types::Value) -> serde_json::Value {
    use prost_types::value::Kind::*;
    use serde_json::Value::*;
    match x.kind {
        Some(x) => match x {
            NullValue(_) => Null,
            BoolValue(v) => Bool(v),
            NumberValue(n) => Number(serde_json::Number::from_f64(n).unwrap()),
            StringValue(s) => String(s),
            ListValue(lst) => Array(lst.values.into_iter().map(prost_to_serde_json).collect()),
            StructValue(v) => Object(
                v.fields
                    .into_iter()
                    .map(|(k, v)| (k, prost_to_serde_json(v)))
                    .collect(),
            ),
        },
        None => panic!("todo"),
    }
}

希望这对你有帮助。

英文:

Adding onto @Caesar's answer, I just wanted to show an example of how to go back and forth between serde_json::Value and prost_types::Value:

fn to_struct(json: serde_json::Map&lt;String, serde_json::Value&gt;) -&gt; prost_types::Struct {
    prost_types::Struct {
        fields: json
            .into_iter()
            .map(|(k, v)| (k, serde_json_to_prost(v)))
            .collect(),
    }
}

fn serde_json_to_prost(json: serde_json::Value) -&gt; prost_types::Value {
    use prost_types::value::Kind::*;
    use serde_json::Value::*;
    prost_types::Value {
        kind: Some(match json {
            Null =&gt; NullValue(0 /* wat? */),
            Bool(v) =&gt; BoolValue(v),
            Number(n) =&gt; NumberValue(n.as_f64().expect(&quot;Non-f64-representable number&quot;)),
            String(s) =&gt; StringValue(s),
            Array(v) =&gt; ListValue(prost_types::ListValue {
                values: v.into_iter().map(serde_json_to_prost).collect(),
            }),
            Object(v) =&gt; StructValue(to_struct(v)),
        }),
    }
}

fn prost_to_serde_json(x: prost_types::Value) -&gt; serde_json::Value {
    use prost_types::value::Kind::*;
    use serde_json::Value::*;
    match x.kind {
        Some(x) =&gt; match x {
            NullValue(_) =&gt; Null,
            BoolValue(v) =&gt; Bool(v),
            NumberValue(n) =&gt; Number(serde_json::Number::from_f64(n).unwrap()),
            StringValue(s) =&gt; String(s),
            ListValue(lst) =&gt; Array(lst.values.into_iter().map(prost_to_serde_json).collect()),
            StructValue(v) =&gt; Object(
                v.fields
                    .into_iter()
                    .map(|(k, v)| (k, prost_to_serde_json(v)))
                    .collect(),
            ),
        },
        None =&gt; panic!(&quot;todo&quot;),
    }
}

huangapple
  • 本文由 发表于 2023年6月16日 04:29:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76485311.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定