1
\$\begingroup\$

A few weeks back I wrote a class to help serialize/deserialize objects file. The file format requested was json, then compressed. After some coding/testing I settled on this design:

class StoreObjects<T>
{
    public IEnumerable<T> LoadObjects()
    {
        List<T> loadObjectList = new List<T>();

        using (Stream stream = new FileStream("fullpathtofile", FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            var js = new JavaScriptSerializer { MaxJsonLength = Int32.MaxValue };

            using (GZipStream gs = new GZipStream(stream, CompressionMode.Decompress))
            {
                do
                {
                    try
                    {
                        var bfs = binaryFormatter.Deserialize(gs);
                        T storeObject = js.Deserialize<T>(bfs as string);
                        loadObjectList.Add(storeObject);
                    }
                    catch (SerializationException se)
                    {
                        //see msdn.microsoft.com/b85344hz.aspx
                        if (se.Message.Contains("Decimal"))
                            throw;
                        //else
                        break;
                    }

                } while (gs != null);
            }
        }

        return loadObjectList;
    }

    public bool SaveObjects(List<T> storedObjects)
    {
        try
        {
            using (FileStream compressedFileStream = File.Create("fullpathtofile"))
            {
                using (GZipStream coStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
                {
                    BinaryFormatter binaryFormatter = new BinaryFormatter();
                    var serializer = new JavaScriptSerializer() { MaxJsonLength = Int32.MaxValue };

                    for (int i = 0; i < storedObjects.Count; i++)
                    {
                        var dump = serializer.Serialize(storedObjects[i]);
                        binaryFormatter.Serialize(compressedFileStream, dump);
                    }
                }
            }
            return true;
        }
        catch (Exception exception)
        {
            //swallow exception on purpose, log error message

        }
        return false;
    }

}

2 design decisions I'm not proud of:

  1. During research, we found that if we passed a very large List of objects, the serialize/deserialize would leak memory. So I settled on a generic class, that you have to pass in a List<T> of the generic to SaveObjects and get back an IEnumerable<T> SaveObjects. As long as your type isn't a very large list, you don't leak memory. BTW, the leak happened when I used json.net also.
  2. In LoadObjects the deserialization stops via an exception check. Because of the nature of deserialize (typically done once for the object tree) and the fact I'm loading lists (see point 1), I have no other way of stopping the deserialization.

It seems to work fine, but I'm not the proud of this design.

\$\endgroup\$
  • \$\begingroup\$ Could you provide a sample of the json data you are de/serializing? Which deserializer throws the exception the binary formatter or the json deserializer? (I guess it's the json deserializer). I suppose there is a decimal number in your json that was serialized with other culture then the deserialization machine. One of them uses the . as decimal separator and the other ,. \$\endgroup\$ – t3chb0t Jul 25 '16 at 8:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.