57

The DataContractJsonSerializer is not able to serialize Dictionaries properly.

Whereas JavaScriptSerializer serializes Dictionaries as {"abc":"xyz","def":42} for example, the DataContractJsonSerializer gives [{"Key":"abc","Value":"xyz"},{"Key":"def","Value":42}] instead.

This is really problematic and I want to know how can I serialize Dictionary objects correctly in my WCF service. I am looking for a solution that would require least amount of effort.

ref: http://msdn.microsoft.com/en-us/library/bb412170.aspx

This is the workaround I finally used to serilize dictionaries properly in WCF: http://social.msdn.microsoft.com/forums/en-US/wcf/thread/765f1569-0422-4471-8ec2-1d03b2026771

jordanhill123
  • 4,142
  • 2
  • 31
  • 40
morpheus
  • 18,676
  • 24
  • 96
  • 159
  • 1
    If you are not using Json.NET, see this: http://stackoverflow.com/questions/7498208/serialize-dictionarytkey-tvalue-to-json-with-datacontractjsonserializer – Mehmet K Oct 23 '14 at 18:18

4 Answers4

64

Using DataContractJsonSerializerSettings (available since .NET 4.5) can do this for you:

var serializer = new DataContractJsonSerializer(typeOfObj, new DataContractJsonSerializerSettings()
{
    UseSimpleDictionaryFormat = true 
});
Community
  • 1
  • 1
Mr.Wang from Next Door
  • 13,670
  • 12
  • 64
  • 97
  • 2
    Hi, where can I replace the "normal" serializer with this serializier when I am create the service host in code? – flayn Sep 05 '17 at 15:25
29

Unfortunately this appears to be by-design, according to the section "Collections, Dictionaries, and Arrays" at http://msdn.microsoft.com/en-us/library/bb412170.aspx

All collections, dictionaries, and arrays are represented in JSON as arrays.

Jarrod Dixon
  • 15,727
  • 9
  • 60
  • 72
Josh
  • 68,005
  • 14
  • 144
  • 156
10

Although this will in most cases cause a major rewrite and thus not be feasible you can let your WCF service interface accept and return Stream in which case you can take full control of serialization. This way you can use JavaScriptSerializer, JSON.NET or ServiceStack.JSON to perform the actual serialization and these serializers actually deals with a dictionaries in a more sensible way.

devdigital
  • 34,151
  • 9
  • 98
  • 120
faester
  • 14,886
  • 5
  • 45
  • 56
  • Did you perhaps mean string instead of stream? – Markus Bruckner Oct 01 '12 at 14:05
  • 3
    @Markus: No, I did not. A string doesn't give you control over the serialization, it gives the method a signature forcing some kind of stirng input whereas `Stream` by convention instructs WCF that you want to take control over serialization. I don't think these two solutions are interchangeable. – faester Oct 01 '12 at 15:04
  • Hmm... i assumed that a return type of string wouldn't be processed either, which seems not to be the case? Otherwise using stream instead of string would by unwieldy, IMO. – Markus Bruckner Oct 01 '12 at 18:54
  • 1
    I guess it depends: If you are using Xml style serialization it will be wrapped. Json (which is of course the pivot of this question) is perhaps another questions since you may get it to work. This doesn't change that WCF has a special use of Streams as both input and return types. It is mainly due to performance issues, but control about serialization is also a point. (WCF simply stops all serialization interceptions and leaves it to you why it is also faster than having WCF intercept your suggested string whereupon you do a different serialization.) – faester Oct 01 '12 at 21:20
  • 1
    Correct, Stream would perform better than a string (as the string would not be subject to the serialization phase) and would guarantee byte for byte that the payload remains unchanged by WCF formatting and serialization. Granted, other stages could modify it, but not in so far as serialization goes. This is a pragmatic solution to the problem. – Josh Nov 12 '12 at 11:25
8

DataContractJsonSerializerSettings has the UseSimpleDictionaryFormat property now and it serializes dictionaries the way you'd expect.

Colin
  • 1,968
  • 2
  • 15
  • 8
  • 3
    Where can I replace the "normal" serializer with this serializier when I am creating the service host in code? – flayn Sep 26 '17 at 12:21