stepancheg / rust-protobuf

Rust implementation of Google protocol buffers

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[protobuf-json-mapping] message with `oneof` cannot be parsed

svanharmelen opened this issue · comments

I'm trying to use either protobuf-json-mapping or custom Serde annotations so I can parse both protobuf and JSON payloads using the same generated structs, but unfortunately both options give me (different) issues.

I guess using protobuf-json-mapping is the preferred solution, so I zoomed in on that one trying debug the issue in order to get a working setup. But it seems I stumbled upon a bug in protobuf-json-mapping which I hope you can maybe shed some light one.

To make it easy to reproduce the issue, I created a debug-example repo with a "working" example giving the error: https://github.com/svanharmelen/debug-example

The problem seems to be related to oneof fields. So for example when using this proto file:

syntax = "proto2";

message TestMessage {
    optional string name      = 1;

    oneof value {
      uint32   int_value    = 3;
      uint64   long_value   = 4;
      float    float_value  = 5;
      double   double_value = 6;
    }
}

Together with this lib.rs:

include!(concat!(env!("OUT_DIR"), "/protos/mod.rs"));

#[cfg(test)]
mod test {
    use crate::example::{test_message::Value, TestMessage};

    #[test]
    fn test() {
        let json = r#"{
          "name": "test",
          "value": 10.3
        }"#;

        let message: TestMessage =
            protobuf_json_mapping::parse_from_str(json).expect("failed to parse JSON");

        assert_eq!(message.name, Some("test".to_string()));
        assert_eq!(message.value, Some(Value::FloatValue(10.3)));
    }
}

When running the test I get this output:

running 1 test
thread 'test::test' panicked at src/lib.rs:15:57:
failed to parse JSON: ParseError { error: ParseErrorWithoutLoc(UnknownFieldName("value")), loc: Loc { line: 3, col: 11 } }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test test::test ... FAILED

So it is unable to find a field called value, which is the name given to the oneof entry in the struct. If I take a look at the fields that are available field_by_name_or_json_name method, I see only the individual fields that are defined inside the oneof:

{"double_value": 4, "floatValue": 3, "float_value": 3, "name": 0, "longValue": 2, "doubleValue": 4, "intValue": 1, "long_value": 2, "int_value": 1}

So how is this suppose to work? Can I do anything configuration wise to fix this? Or is this actually a bug? And in case the latter, I'm open to having a look how to solve it, but then I do need a few pointers to get me started 😊

Thanks!

I found a solution (not the best, but it works) so I'll close this one...

I found a solution (not the best, but it works) so I'll close this one...

what's the solution?