1

Closed

TypeNameHandling.Auto and ISerializable

description

Rather than repeating myself, I had recently posted a question on StackOverflow regarding missing $type property when using TypeNameHandling.Auto along with ISerializable.

Using ISerializable.GetObjectData not setting $type despite TypeNameHandling.Auto

When SerializeISerializable starts to serialize each SerializationEntry, there is no ItemContract associated with JsonContainerContract and thus it does not write out type (ShouldWriteType line 821).

Given that GetObjectdata will always havetypeof(object) for the value, I would expect that $type should always be written with TypeNamehandling.Auto?

Example classes may be found in StackOverflow link above.
Closed Jun 6, 2013 at 5:59 AM by JamesNK
Done

comments

CBaxter wrote Jun 1, 2013 at 6:39 PM

Initial testing shows that with a small modification to ShouldWriteType illustrated below, the $type property will be added when serializing via ISerializable interface. All unit tests will still pass, and serialization will be consistent with serialization of a Dictionary<String, Object>.

Current Code (line 821)
        else if (containerContract != null && containerContract.ItemContract != null)
        {
          if (contract.UnderlyingType != containerContract.ItemContract.CreatedType)
            return true;
        }
Proposed Code (line 821)
        else if (containerContract != null)
        {
            if (containerContract.ItemContract == null || contract.UnderlyingType != containerContract.ItemContract.CreatedType)
                return true;
        }          

JamesNK wrote Jun 3, 2013 at 3:49 AM

I don't see the point. The type still has to be explicitly specified in the ISerializable constructor when deserializing.

CBaxter wrote Jun 3, 2013 at 5:04 AM

No, I could simply ask for an instance of SomeBase in the constructor and not know the derived type inside the ctor (unless I am missing something?). The lack of a $type being serialized on the value of the Child property of MyParent means that the object type is unknown when attempting to deserialize the object (i.e., Child property value could be an instance of MyChild or MyOtherChild as long as it derives from SomeBase.

As mentioned on SO, when the MyParent object is annotated with DataMember attributes, the resulting JSON includes the $type property for `Child:
{"c":{"$type":"...+MyChild,...","p":"My Test String"}}
I would have expected the same behavior when using ISerializable which omits the $type property.
{"c":{"p":"My Test String"}}
I personally did not think that using ISerializable would behave any different as the object being serialized does not match the declared property type (and impo is really just serializing an IDictionary<String,Object>).

JamesNK wrote Jun 4, 2013 at 2:42 AM

Ok, if in the constructor you're just asking for a SomeBase then I can see why it would be useful.

CBaxter wrote Jun 5, 2013 at 4:08 AM

I have set up custom JsonConverters the mean time rather than set TypeNameHandling.All as a work around in my project, but it would be great to see this addressed in a future version (always happy to delete code).

Thank you.