Serde: how to debug Deserialize impl

I'm trying to debug my serde::Deserialize impl for a data structure I have. I already use serde_test::assert_tokens and it runs successfully. But now I created another test that actually ser & deser's using bincode—and oddly enough, that one crashes. Returns the error invalid type: sequence, expected struct Node when calling bincode::deserialize(<serialized bytes>).unwrap().

How does one generally debug serde::Deserialize implementations like this? I don't know where to start or how to get more info to see what might be going wrong.

It sounds like either your serialize and deserialize implementations don't match up and something is trying to be deserialized as a Node struct when that part of the byte stream was serialized as a sequence of things.

Something that might help is to write tests that make sure each field in your type serializes and deserializes correctly. That'll help you know what type the dodgy Serialize/Deserialize implementation comes from.

I would also take the same tokens you passed to serde_test::assert_tokens() and make sure they can be used with serde_test::assert_de_tokens(). That should hopefully give you more useful error messages that point to the exact token/field that was serialized/deserialized incorrectly.

1 Like

According to the docs, assert_tokens already calls assert_de_tokens, too. The weird thing is that this assert passes.

I don't get how these token tests can pass even though the Deserialize implementation seems to be broken? That's what's confusing me. In that case, what does assert_de_tokens even test if it doesn't assert correctness?

I guess I could write unit tests for the smaller Deserialize impls that make up "the larger one", but there I would only call the same assert_tokens that I'm already calling in my big integration test, just with a subset of the test data. But the big integration test that calls assert_tokens is already passing... so I don't see how that'd improve things.

1 Like

For posterity: My error was dependent on the serialization format. I forgot to implement the visit_seq method in my Visitor and only implemented visit_map. The ser format I used (bincode) didn't encode it as a map, but as a seq.

=> for format-independent ser/deser, implement both visit_seq and visit_map.