Skip to content

Numbers in JSON Serializer Keys #39

@mitsuhiko

Description

@mitsuhiko

It's not clear right now how numbers as key in JSON are best to be supported. Right now this would fail as the number serializer and deserializer does not accept numbers encoded in strings. However that's effectively what one would need to do to support integers as hash maps.

This problem is somewhat tricky because there is no way right not to customize behavior within nested structures. The only customization is really only available on the level of the derive. So this hypothetical example does not work:

#[derive(Serialize, Deserialize)]
pub struct MyThing {
    map: HashMap<#[deser(as_string)] u32, bool>,
}

One hypothetical option would be to make the concept of "funnel through string" a property of the serialization system. In that case the u32 serializer and deserializer could probe the state to figure out if the current context requires supporting deserializing from a string. Something like this:

impl Sink for SlotWrapper<u32> {
    fn atom(&mut self, atom: Atom, state: &DeserializerState) -> Result<(), Error> {
        match atom {
            Atom::Str(s) if state.uses_string_tunneling() => {
                if let Ok(value) = s.parse() {
                    **self = Some(value);
                } else {
                    Err(Error::new(
                        ErrorKind::Unexpected,
                        "invalid value for number",
                    ))
                }
            }
            Atom::U64(value) => {
                let truncated = value as u32;
                if truncated as u64 == value {
                    **self = Some(truncated);
                    Ok(())
                } else {
                    Err(Error::new(
                        ErrorKind::OutOfRange,
                        "value out of range for type",
                    ))
                }
            }
            Atom::I64(value) => {
                let truncated = value as u32;
                if truncated as i64 == value {
                    **self = Some(truncated);
                    Ok(())
                } else {
                    Err(Error::new(
                        ErrorKind::OutOfRange,
                        "value out of range for type",
                    ))
                }
            }
            other => self.unexpected_atom(other, state),
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions