StefanS
StefanS

Reputation: 71

Deserializing Collections with protobuf-net

During my switch from BinaryFormatter to protobuf-net, I observed a difference when serializing collections.

In the code sample below, Deserialize (protobuf-net v2r470) returns different results if an array is instantiated within the class (street1) than outside (street2).

Is it not allowed to serialize collections instatiated within a class declaration?

[ProtoContract]
public class City
{
    [ProtoMember(1)]
    public string[] streets1;

    [ProtoMember(2)]
    public string[] streets2 = new string[2];
}

City city = new City();

// Instantiate and populate streets1
city.streets1 = new string[2];
city.streets1[0] = "streetA";
city.streets1[1] = "streetB";

// Populate streets2. Already instantiated
city.streets2[0] = "streetA";
city.streets2[1] = "streetB";

// Serializing
using (var file = File.Create("city.bin"))
{
    Serializer.Serialize(file, city);
}

// Deserializing
using (var file = File.OpenRead("city.bin"))
{
    City  getCity = Serializer.Deserialize<City>(file);
}

Deserialize loads the following in getCity:

getCity.streets1: "streetA", "streetB" (as expected)

getCity.streets2: null, null, "streetA", "streetB" <--------- Why the null's ?

There are as many null's returned as there are items in the collection.

Upvotes: 2

Views: 1827

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064324

It is, but the problem is that protobuf-net assumes (due to the concatenatable nature of the protobuf format) that it should extend (append to) lists/arrays, and your field-initializer is starting it at length 2.

There are at least 3 fixes here:

  • you can add SkipConstructor=true to the ProtoContract, which will mean it doesn't run the field initializer
  • there is a "replace lists" syntax on ProtoMember which tells it to replace rather than append (I can't remember the actual option, but it is there)
  • you can add a before-deserialization callback to clear the field between the constructor and the deserialization

Upvotes: 3

Related Questions