Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@xordi
Copy link
Contributor

@xordi xordi commented Oct 3, 2024

Issue description

Ignored enum values cause a deserialization error when using thefrom_value function.

How to reproduce

This code produces an error saying incorrect value of type: Enum:

struct SampleStruct {
    a: String
}

let record = Value::Record(vec![
    (
        "a".to_string(),
        Value::String("a valid message field".to_string()),
    ),
    (
        "a_non_existing_enum".to_string(),
        Value::Enum(0, "Variant1".to_owned()),
    )
]);

let deserialized: SampleStruct = from_value(&record)?;

Proposal

I see the deserialize_any function is basically called only from deserialize_ignored_any.

I might have also made a wrong assumption, but it seems unlikely that from_value will be used to deserialize into a type that its Deserialize implementation calls deserialize_any, as the Value passed as a parameter already represents an arbitrary Avro value. For that reason I opted to call the visit_borrowed_str on the visitor when finding a Value::Enum inside deserialize_any, avoiding allocating further memory. I would appreciate any further insight on this though, as I'm not sure if it's the right approach.

@martin-g martin-g changed the title Fix deserializing ignored enum fix: deserializing ignored enum Oct 4, 2024
@martin-g
Copy link
Member

martin-g commented Oct 4, 2024

I would appreciate any further insight on this though, as I'm not sure if it's the right approach.

Me too :-/

How is a_non_existing_enum supposed to be handled ? It seems it is just being ignored in your example. Why ?

@martin-g martin-g merged commit 3ac24ef into apache:main Oct 4, 2024
@martin-g
Copy link
Member

martin-g commented Oct 4, 2024

It seems it is just being ignored in your example. Why ?

I still do not understand why it behaves like that but I see that the test does the same for all other fields, so you just follow the pattern.
If you understand why the extra record fields are being silently ignored please share!

@martin-g
Copy link
Member

martin-g commented Oct 4, 2024

Thank you, @xordi !

@xordi
Copy link
Contributor Author

xordi commented Oct 4, 2024

Ignoring those fields is on purpose, as I'd like to be able to deserialize the Value into a struct with just a subset of the fields that are present in the Value::Record.

serde produces a Deserialize implementation on the type that accounts for ignored fields. Basically that implementation calls deserialize_ignored_any in the Deserializer when handling a field that's not present in the target element (a struct in this case). I guess the main reason of this is because in some data formats, you need to read the underlying stream of data and ignore it in order to decode the next elements. In this crate case, the Deserializer forwards deserialize_ignored_any (called by the serde implementation of Deserialize on the struct) to deserialize_any, where the Enum values are not handled.

I followed the same pattern as for the other Value types in this fix, as this is actually implemented for mostly all of them except for Enum. I wonder if there was any reason why this behavior was not replicated for enums. I don't see any, but of course I might lack a lot of context.

Maybe another option not impacting this crate would be to manually implement Deserialize for a struct in which we just want to deserialize certain fields from the Value::Record, but given that the Deserializer implementation was already ignoring fields of other types, I opted to implement the same for enums.

@xordi xordi mentioned this pull request Mar 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants