9 Comments

I'm working on a little internal app that involves some AJAX-y callbacks to the server for data. The data is returned in JSON format for easy consumption by the client side code and is being generated with very un-sexy Response.Writes, whose output looks something like this:

{
   "jbloggs" : 
   {
      fullName : "Fred Bloggs",
      title : "Chief Burger Flipper",
      tel : "512"
   },
   "jdoe" : 
   {
      fullName : "Jane Doe",
      title : "Assistant Burger Flipper",
      tel : "587"
   },
   ...
}

This works nicely as a information can be looked up on the client in JavaScript like so:

var person = peopleJson["jbloggs"];
alert(person.fullName);

Dead easy. JavaScript objects are just dictionaries/hash tables.

Now I was aware that Windows Communication Foundation (WCF) services can now do JSON serialization in .NET 3.5, so I thought I'd swap out my low-tech Response.Writes for a WCF Service that would let me come up with structures in my server-side code that would be serialized automatically to JSON. But I found that the the way WCF (which ultimately uses DataContractJsonSerializer) serializes Dictionaries is a bit lame. This is what it came up with:

[
   {
      "Key":"jbloggs",
      "Value":
      {
         fullName : "Joe Bloggs",
         title : "Chief Burger Flipper",
         tel : "512"
      }
   },
   {
      "Key":"jdoe",
      "Value":
      {
         fullName : "John Doe",
         title : "Assistant Burger Flipper",
         tel : "587"
      }
   },
   ...
]

Odd. Dictionaries are serialised as arrays of objects whose members consist of a Key and Value. So in order to look up an entry I'd have to do a linear search through this array. I mean, you would have thought the fact there is dictionary functionality built-in to the JavaScript Object prototype (in fact, fundamental to JavaScript) - that it would be the sensible format to use rather than the Key/Value format. I just can't quite see why Microsoft thought that this Key/Value format was necessary as it's such a pain to consume on the client.

Looks like my low-tech Response.Writes are going to get a stay of execution for the time being.

Comments

Comment by James

You mean you want them to special case the JSON serialiser that works for any Dictionary to provide different behaviour when K = String? That would be... far too useful.

Actually, it looks like they haven't even specifically catered for Dictionary at all, and just treated it as an IEnumerable<DictionaryEntry>... yuck.

Surely WCF's flexible extensible declarative configuration architecture provides for you to implement IJSonSerializationFormatAdaptorFactoryFactory and configure a SerialisationFormatAdaptorEndpointBinding on your service, though.

James
Comment by Andy

James,

You may well be right. I'm still learning WCF and have no clue what you are talking about. And that's the problem.

This is fundamental JavaScript. Why does Microsoft make the common case hard?

Andy
Comment by Rui

Hi,

any solution to this "problem"?

Rui
Comment by RK

Yes, but the .NET dictionary could have keys that are not valid JavaScript identifiers.

Would
{
"3*5/8" : "John Doe",
"title" : "Assistant Burger Flipper"
}

be a legitimate JavaScript object?

Person.title would make sense, and maybe Person["3*5/8"] (not sure about that), but Person.3*5/8 doesn't make any sense.

RK
Comment by Duncan Smart

The 2nd syntax is fine if you keys are going to be arbitrary strings.

Comment by Duncan Smart

But js disctionary keys are just strings, e.g.:

{
fullName : "John Doe",
title : "Assistant Burger Flipper",
tel : "587"
}

is shorthand for:

{
"fullName" : "John Doe",
"title" : "Assistant Burger Flipper",
"tel" : "587"
}

Of course, of your .NET dictionary has keys of DateTime or some other object, then I quite understand why they went the they did.

Check out Json.NET: http://www.codeplex.com/Json

Comment by RK

I thought about this some more and think what MS is doing is fine.

Think about this -- not all dictionary keys will be legitimate Javascript property names.

Writing my own serializer seems to be the way to go.

RK
Comment by RK

I don't know what a IJSonSerializationFormatAdaptorFactoryFactory is. Didn't see it in the docs, and it sounds aggrevating.

I'm facing a similar problem. I'm thinking of writing a Javascript shim that takes the Name/Value JSON object and builds a Javascript object with properties named with the name and values that are the values.

This type of solution won't be useful, however, if you don't have control of the client end too.

I'm interested in anyone else's thoughts on this too.

RK