1

TL;DR; Is there a library or protocol that allows me to serialize some data from a .NET app and deserialize on WP, Win8, iOS and Android while preserving references between objects as they were in code i.e. if a single instance X is a member of Y and Z when Y and Z are deserialized there should be only one X object.

Detailed version:

I want to be able to serialize some objects of types A and B where A has a member of type B and one instance of B can be a member of many instances of A. I should be able to deserialize on WP, Win8, iOS and Android and the same relations should be kept when the data is deserialized. Sadly I cannot test on Android and iOS right now.

The requirements for the serialization mechanism

  • Preserve object references when deserializing
  • The overhead of the serialization is not really important because the device will get new data like once in three months
  • while the overhead is not important it is important that references to the same object are not serialized more once because this can result in very large serialized data.
  • be able to serialize with .NET. Serializing on other platforms is not required.
  • be able to deserialize on WP, Win8, iOS, Android


[DataContract(IsReference = true)]
public class A
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public B MemberB { get; set; }
}

[DataContract(IsReference = true)] public class B { [DataMember] public string Name { get; set; } }

Example object graph:


var b1 = new B { Name = "B1" };
var aa = new List { new A { MemberB = b1, Name = "A1" }, new A { MemberB = b1, Name = "A2" } };

I have tried using DataContract Serialization and adding IsReference = true to the DataContract attribute. This works like a charm between desktop .NET and WP and I assume it will work on Windows 8 but I could not even find a way to deserialize DataContractSerialization on iOS and Android without writing my own deserializer let alone out of the box support for preserving references. DataContract serialization will be perfect for me if there is a library that provides deserialization on iOS and Android without additional effort.

I also experimented with an OData service. OData has client libraries for iOS and Android but does it work as expected. It seems like if there is a PK on the entity references will be preserved. I tested on WP and .NET console app like this:

DemoService service = new DemoService(new Uri("http://services.odata.org/OData/OData.svc/"));
var productsQuery = (DataServiceQuery<Product>)
                    (from p in service.Products.Expand("Category")
                     where p.Category.ID == 1
                     select p);

productsQuery.BeginExecute(
    (result) =>
        {
            var actualProducts = productsQuery.EndExecute(result).ToList();
            System.Diagnostics.Debug.WriteLine(actualProducts[2].Category == actualProducts[4].Category); //outputs true because both categories are the same
        },
    null);

It seems it works but am I doing the testing right and does it work like this with iOS and Android clients? I would like to avoid OData because it seems too heavy for my case.

I realize I can give each object an ID and only use the IDs to model the object graph but I am hoping for a cleaner solution. I also want to avoid writing my own serialization code.

Subquestions:

  1. Is there a way to deserialize DataContract Serialization on iOS and Android without writing my own deserializer
  2. Does the OData clients for iOS and Android preserve object references? Are they easy to work with
  3. Do Mono for iOS and Mono for Android suppord DataContract deserialization while preserving object references?

Thanks for your time.

Charles
  • 50,943
  • 13
  • 104
  • 142
Stilgar
  • 22,354
  • 14
  • 64
  • 101
  • Edit: the comment I was replying to is now gone. JSON by itself does not provide any way to preserve object references in graph-like fashion. It only provides ways to preserve object trees. I would gladly use JSON serializer that can preserve object references. Serializers achieve this by assigning each object an ID and referencing the ID when the object is serialized again. When deserializing the deserializer stores the already deserialized objects and when an ID in the stream the existing object is used. This can be achieved with JSON as well but the deserializer needs to support it. – Stilgar Sep 04 '12 at 14:58

1 Answers1

3

I would use protocol buffers from google. There are other implementations for other languages including Objective C and C#.

Update:

If I was doing this I would start by using .NET everywhere including on Android (by using MonoDroid) and (MonoTouch on iOS). Yes you can now share C# code across any your platforms!

Each of my objects that I wished to serialize would have an equivalent object defined as a Protocol-Buffer object. Each object would have a serialized hash-value as it's ID. Each Reference in the object would be defined as a hash-value.

You then have some code in each objects to walk the objects below it, serializing to the protocol buffer object as you go. Populating the hash-value references.

Each object reference gets look-up and stored in a dictionary (hash-value/address) of objects if it's not present. This is also serialized. This stops you serializing objects twice as the object is only serialised/deserialised once across the whole operation. This is done by setting/clearing the address of the object in the dictionary.

I've written this stuff before it isn't a big deal.

AnthonyLambert
  • 8,768
  • 4
  • 37
  • 72
  • According to this discussion it seems like protocol buffers do not provide an option to preserve references: https://groups.google.com/forum/?fromgroups#!topic/protobuf/1agQYJxp2mo As far as I know size of the message is the main benefit of protocol buffers and since I don't really care about the size of the message I'd rather use something more ubiquitous like JSOn or XML. – Stilgar Sep 04 '12 at 14:53
  • Neither maintains object references. :-) What about Python's Pickles? :-) It's not hard, compact, and handles object references. You might have to implement it yourself - which is I think not what you want to do. – Kobor42 Sep 04 '12 at 15:03
  • Using Python serialization to serialize in .NET and deserialize it in Java and Objective-C? :) – Stilgar Sep 04 '12 at 15:06
  • some versions of Protocol buffers do maintain the object graph... see: http://stackoverflow.com/questions/6294295/protobuf-net-serializing-object-graph – AnthonyLambert Sep 04 '12 at 16:02
  • @AnthonyLambert Interesting. Still the question remains the same as with other options. Can I serialize like this with .NET and deserialize on WP, Win8, Android, iOS. Support in only one library won't be enough. – Stilgar Sep 04 '12 at 16:07
  • Regarding your updated answer: If you have .NET on all sides why not use DataContract serializer that supports this feature out of the box (assuming Mono for iOS and Android do support it)? – Stilgar Sep 04 '12 at 21:24
  • It's a valid point, personally I'm not looking to serialize references at all and will use protocol buffers (PB) to send defined messages containing arrays of PB objects. Down the line I wish to allow interfaces for other languages. I can do that by publishing the PB definition files. – AnthonyLambert Sep 06 '12 at 11:20