I am using DataContractJsonSerializer
to serialize/deserialize my object to/from JSON string. My object contains a Dictionary<string, string>
data member, and I want to make this dictionary case insensitive after deserialization. Currently, after ReadObject
, I manually create a new dictionary explicitly with StringComparer.OrdinalIgnoreCase
, and copy the content to the new dictionary. This looks ugly. Is there some way to do this more elegantly? Like controlling the object creation when deserializing?

- 104,963
- 20
- 228
- 340

- 723
- 7
- 22
1 Answers
The data contract serializers are able to serialize and deserialize get-only collection properties as long as the returned collection is pre-allocated. (This is in contrast with other types of get-only property, which cannot be serialized directly.) However, since the constructors of data contract objects are not called, it is necessary to pre-allocate somewhere else, e.g. in an OnDeserializing
method, or in the getter itself:
[DataContract]
public class RootObject
{
Dictionary<string, string> dictionary;
[DataMember]
public Dictionary<string, string> Dictionary
{
get
{
if (dictionary == null)
System.Threading.Interlocked.CompareExchange(ref dictionary, new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase), null);
return dictionary;
}
// DO NOT ADD A SET METHOD EVEN IF PRIVATE, it will break data contract serialization.
}
}
The Dictionary
data member will now be deserialized into your pre-allocated Dictionary<string, string>
that uses StringComparer.OrdinalIgnoreCase
.
Notes:
There cannot be a set method, even one that is private. If there is, the data contract serializers will construct their own
Dictionary<string, string>
and set it back, ignoring the pre-allocated dictionary.Since the default constructors for collection data contract objects are called, you could instead subclass
Dictionary<string, TValue>
and set an appropriate comparer in the constructor, e.g. as follows:public class OrdinalIgnoreCaseDictionary<TValue> : Dictionary<string, TValue> { public OrdinalIgnoreCaseDictionary() : base(StringComparer.OrdinalIgnoreCase) { } } [DataContract] public class RootObject { [DataMember] public OrdinalIgnoreCaseDictionary<string> Dictionary { get; set; } }

- 104,963
- 20
- 228
- 340