Providing serde Deserializing support alongside proto for enum

I have tackled several layers to the task using tonic_build "type attributes".

An overview of the issue

proto -> rust for an enum looks like:

// proto
enum Purpose {
    SUBJECT   = 0;
    QUALITY   = 1;
}
// rs
#[derive(Deserialize_repr)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum Purpose {
    Subject = 0,
    Quality = 1,
}

json -> rust for the enum

... a snippet

{
     "idx": 2,
     "purpose": "quality"
}

... but, when using the Purpose value in a "host/parent" type, Purpose is encoded using i32.

// rs
// Field has a Purpose
#[derive(Deserialize)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Field {
    #[prost(uint32, tag="1")]
    pub idx: u32,
    #[prost(enumeration="Purpose", tag="4")]
    pub purpose: i32,
}

... ok, we have a c-type enum. I get that, but am having a tough time relating this is how serde works.

There is a serde_repr "helper" package for the typical version of this problem. However, it does not deserialize as expected. I can "get it to go" when I substitute the purpose string values to an integer.

Otherwise, it fails when it hits the json: { ... "purpose": "subject" }.

ERROR:
  Code: Internal
  Message: invalid type: string "subject", expected i32 at line 22 column 32

The docs focus on how the enum can be represented, nothing explicit about how to accomplish the task for the parent reference (not something I would need if it weren't for where this error seems to be pointing :))

Furthermore, the "helper" package describes how to "serialize" to an integer. That would imply int -> enum::variant = int_value for the deserialization process... consistent with the error and my using the "typical" qualification earlier. It makes me think the right combination is Deserialize with rep[i43], but thus far, no luck

Any ideas?

Your Field struct's purpose field has type i32 not Purpose. I believe that's correct for prost, but it's gonna cause you problems with serde.

You could potentially use serde's with field attribute to deserialize purpose as a string and then convert it to an integer (and vice versa for serializing) to make it match the protobuf schema. You'll have to write some manual serde functions though.

It may be simpler in the long term to define a separate set of types for your JSON data model if the schema doesn't line up exactly with your protobuf schema. The requirements of a good JSON schema aren't always going to line up with how protobuf does things.

@semicoleon you are likely right regarding the "ideal design". Unfortunately, you might also be right for a "quick pop-up" of some testing capacity as I build through this part of the project; testing where the focus is on the proto functionality.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.