Cannot serialize Vec<Vec<FieldValue>> with serde

Hi community !

This is my code:

#[derive(Debug, Clone, PartialEq)]
pub enum FieldValue {
    Integer(i32),
    IntegerArray(Vec<i32>),
    Long(u64),
    LongArray(Vec<u64>),
    Float(f32),
    FloatArray(Vec<f32>),
    Bytes(u32),
    BytesArray(Vec<u32>),
    TwoShorts((i16, i16)),
    TwoShortsArray(Vec<(i16, i16)>),
    Custom(Vec<FieldValue>),
    CustomArray(Vec<Vec<FieldValue>>),
    None,
}

impl Serialize for FieldValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match self {
            FieldValue::Integer(value) => serializer.serialize_i32(*value),
            FieldValue::IntegerArray(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    seq.serialize_element(&item)?;
                }
                seq.end()
            }
            FieldValue::Long(value) => serializer.serialize_u64(*value),
            FieldValue::LongArray(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    seq.serialize_element(&item)?;
                }
                seq.end()
            },
            FieldValue::Float(value) => serializer.serialize_f32((value * 100.0).round() / 100.0),
            FieldValue::FloatArray(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    let item = (item * 100.0).round() / 100.0;
                    seq.serialize_element(&item)?;
                }
                seq.end()
            },
            FieldValue::Bytes(value) => serializer.serialize_u32(*value),
            FieldValue::BytesArray(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    seq.serialize_element(&item)?;
                }
                seq.end()
            },
            FieldValue::TwoShorts((value1, value2)) => {
                let mut tuple = serializer.serialize_tuple(2)?;
                tuple.serialize_element(&value1)?;
                tuple.serialize_element(&value2)?;
                tuple.end()
            },
            FieldValue::TwoShortsArray(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    seq.serialize_element(&item)?;
                }
                seq.end()
            },
            FieldValue::Custom(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    seq.serialize_element(&item)?;
                }
                seq.end()
            },
            FieldValue::CustomArray(array) => {
                let mut seq = serializer.serialize_seq(Some(array.len()))?;
                for item in array {
                    let mut inner_seq = serializer.serialize_seq(Some(item.len()))?;
                    for inner_item in item {
                        inner_seq.serialize_element(&inner_item)?;
                    }
                    inner_seq.end()?;
                }
                seq.end()
            },
            FieldValue::None => serializer.serialize_none(),
        }
    }
}

on compile I have an error:

error[E0382]: use of moved value: `serializer`
   --> src/primary/traits/src/types/update_fields.rs:529:41
    |
471 |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
    |                            ---------- move occurs because `serializer` has type `S`, which does not implement the `Copy` trait
...
527 |                 let mut seq = serializer.serialize_seq(Some(array.len()))?;
    |                               ---------- value moved here
528 |                 for item in array {
529 |                     let mut inner_seq = serializer.serialize_seq(Some(item.len()))?;
    |                                         ^^^^^^^^^^ value used here after move
    |
help: if `S` implemented `Clone`, you could clone the value
   --> src/primary/traits/src/types/update_fields.rs:471:18
    |
471 |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
    |                  ^ consider constraining this type parameter with `Clone`
...
527 |                 let mut seq = serializer.serialize_seq(Some(array.len()))?;
    |                               ---------- you could clone this value
help: consider further restricting this bound
    |
471 |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer + std::marker::Copy {

but when I try to add + Copy I got another error:

error[E0276]: impl has stricter requirements than trait

This is a sandbox to reproduce: Rust Playground

Could somebody explain me how to fix this issue ?

You can do this:

FieldValue::CustomArray(array) => {
    let mut seq = serializer.serialize_seq(Some(array.len()))?;
    for item in array {
        seq.serialize_element(item)?;
    }
    seq.end()
},

or just this:

FieldValue::CustomArray(array) => serializer.collect_seq(array),
1 Like

So easy... I thought I should serialize nested array separately.
Thank you !

No, why? Vec<T>: Serialize if T: Serialize; and in any case, if you were required to expand every layer of arrays and maps manually, then it would be impossible to write generic serialization code, since you couldn't account for all layers of arrays in an arbitrary type substituted for a type parameter. It just wouldn't make any sense.

Your attempt at calling serialize_seq() twice on the same serializer was, by the way, incorrect because serialization is an inherently recursive problem. An object serializes its own representation, then recurses into the sub-objects or items. Once you started serializing a sequence, you should obviously be using the returned sequence serializer – otherwise, if you opened the inner sequence serializer using the original, top-level serializer, it would not know the correct nesting level. It'd just be unnatural.


Why aren't you just deriving the Serialize impl, by the way? All this boilerplate you are writing seems completely unnecessary. It should be identical to the code generated by #[derive(Serialize)].

1 Like

It's really quite rare that you have to implement serialize yourself. Something like this is usually all that's needed:

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum FieldValue {
    Integer(i32),
    IntegerArray(Vec<i32>),
    Long(u64),
    LongArray(Vec<u64>),
    Float(f32),
    FloatArray(Vec<f32>),
    Bytes(u32),
    BytesArray(Vec<u32>),
    TwoShorts((i16, i16)),
    TwoShortsArray(Vec<(i16, i16)>),
    Custom(Vec<FieldValue>),
    CustomArray(Vec<Vec<FieldValue>>),
    None,
}
1 Like

…with a #[serde(untagged)] on the trailing unit variant (or the whole enum).

1 Like

Thanks for detailed explanation. I use manual serialization, because otherwise I will receive redundant data in output. For example:

"object_fields": {
    "ObjectField::ENTRY": {
        "Integer":1234,
    },
    "ObjectField::GUID": {
        "Long":1234123412341234
    }
}

I do not need this "Integer" and "Long" there, I need only value. So with manual serialization I have this:

"object_fields": {
    "ObjectFIeld::ENTRY": 1234,
    "ObjectField::GUID": 1234123412341234
}

This code is the part of my big project btw: GitHub - idewave/tentacli: Rust implementation of world of warcraft client v3.3.5a (smart CLI)

I am not sure if I understand this part, could you add more details ?

That's exactly what the untagged representation means. Please consult the documentation of Serde. There's no need for me to repeat what's readily available at the obvious place.

1 Like

Link to the doc :melting_face:

3 Likes

Thank you, I got what you meant. Yep, now it is much better.

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.