Click here to Skip to main content
Click here to Skip to main content

Generic C# JSON Generator to Send Any Data to JavaScript

By , 17 Feb 2009
 

Introduction

How would you like to have any data in C# (like this 3.5 sample)...

C#

... and access it from JavaScript, using the same syntax as in C#:

Javascript

"How Do They Do It?"

So there I was building a simple Ajax application using ASP.NET and it was very hard to send data from the code-behind in ASP.NET to the JavaScript code. Then I found out about JSON, which solved all the problems. The nice thing about JSON is that it is a format that browsers understand and can use to create rather complex data inside their JavaScript engines. So I wrote a recursive reflection based JSON generator that takes any managed class or struct and generates the JSON string that the browser understands.

Because this engine searches for fields in the class, there's no need to write such properties:

public int Id
{
    get { return this._id; }
    set { this._id = value; }
}

You can either select all fields or mark specific fields with an attribute and only send them to the JavaScript code.

More than that, the engine can handle even the anonymous types specific to .NET 3.5 (as seen in the picture above). It seems that the anonymous types are not stored identically to the proper types in the assembly's DLL.

Using the Code

Using the code is as simple as it gets: with one line of C# code you "convert" the object to the JSON string that is sent to the client code. No need for helper classes (like type serializers).

The client code uses one eval line of code to create the DOM object.

And that's it. In .NET 3.5, you don't even have to write the class with the complex constructor to receive all the data as parameters (as it was the case in .NET 2.0).

The engine can handle primitive data types (numeric types, strings and dates), classes, structs, arrays and null fields. If you have some data in a custom collection (like generic Lists), you can use the ToArray() method to get in a form the engine understands. I've chosen to use array(s) instead of IEnumerable(s) because you might have a class that implements IEnumerable but you might not want to treat it as a collection (string is such a class).

I know the whole point of this engine is to hide the representation of the object, but here's an example of how it looks (just to have an idea).

{
    'date' : new Date( 2008, 1, 23, 8, 5, 52 ) ,
    'Name' : 'some string' ,
    'StringSpecial' : '\\some \' \" string' ,
    'NullString' : null ,
    'Private' : null ,
    'i' : -1 ,
    'f' : 2.3 ,
    't2' :
    {
        'd' : 3.14 ,
        'D' : 3.15 ,
        'ThisIsAStruct' :
        {
            'str' : 'string in a struct'
        }
    }
}

Now that you've been briefed, go and download the archive and try it out.

There's a Visual Studio 2005 and a Visual Studio 2008 solution. The last one includes a .NET 3.5 ASP sample to test the anonymous types I was bragging about.

If you take a look at the generator's code, you'll notice it is not even 200 lines of code long.

PS: Don't forget to set the Web project as the "start up project" inside Visual Studio.

History

  • Feb 23rd, 2008 - Initial version
  • Feb 16th, 2009 - New code version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mihai Maerean
Software Developer (Senior)
Romania Romania
Member
Areas Of Expertise:


APIs:

.Net Framework
MFC
Win32
 
ActiveX (documents, controls, automation)
 
Graphics:

DirectX
OpenGL
 
Databases:

SQL Server
ADO
Odbc
 
Web Applications:

AJAX
ASP.Net
Web Services
ActiveX controls
 
Programming Languages:

C/C++
C#
Pascal
Basic
Python
Javascript
XHTML
 
Proud to have been part of the following team(s):

Project Viewer - Housatonic

Silent Hunter 4 - Ubisoft Romania
 
Personal web site (programing C++ C# ASP.NET, CV, jokes, games)
 
RedGoblin - boardgames store (a project i'm working on)
 




Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionJsonBridge does it easier and with no headache...memberEvgenios Skitsanos2 Jun '12 - 9:51 
Salut Mihai,
 
I think you need to look at my JsonBridge (http://jsonbridge.com) or you can have a look at samples directly on http://jsonbridge.mywdk.com
 
Cheers,
Evgenios
GeneralAn idea building on thismemberdojohansen20 Feb '09 - 4:01 
Hi,
 
I would like to suggest a little project to improve on this. The idea of using JSON instead of XML (or in practice, using the XML only as an envelope to enable using XmlHttpRequest) is in many ways a good one, since it describes an object graph.
 
However, reflection is quite slow, and that limits the usefulness of any reflection-based approach a little. So I was thinking how about using reflection together with code DOM to create not JSON but a C# hardcoded JSON serializer for a given type instead - something like this:
 
static public class JsonSerializer 
{
    static object syncRoot = new object();
    static Dictionary<Type, IJsonSerializer> cache = new Dictionary<Type, IJsonSerializer>();
 
    static public string Serialize(object obj)
    {
        Type t = obj.GetType();
        IJsonSerializer s;
        if (!cache.TryGetValue(t, out s))
        {
            s = JsonSerializerFactory.GetSerializer(t);
            cache.Add(t, s);
        }
        return s.Serialize(obj);
    }
}
 
Where the IJsonSerializer interface has one method: string Serialize(object obj). This is inspired by the FrameWork's "compiled regex" expressions, which are in fact the same thing: The external world sees the RegEx class, but when it's compiled, a new type is in fact created and compiled optimized for the given expression, and is what does all the actual work. This of course adds overhead on first use, but is much more efficient on subsequent instances. (The .net serialization system also uses dynamic compilation rather than reflection, and I did the reverse there, making a reflection-based serializer so I could serialize and deserialize non-public fields. Both approaches have their respective merits..!)
 
I've implemented this and measuring with System.Diagnostics.Stopwatch (which can measure very tiny intervals of time on modern computers) the compiled serializer is well over 100 times faster than the reflection-based approach. It may not matter much in a lot of cases, but it's pretty cool and not so hard -- the serialization itself is harder than generating the class for a given type.
 
I guess I could write an article but my serializer is incomplete (I thought it a bit tedious since my focus was on the CodeDOM bit) and I figure you can go one better applying my idea to your serializer.
 
If you are interested in seeing what I did, just PM me and I'll get in touch.
GeneralNot working with an array of objetmemberAVAUX15 Feb '09 - 22:57 
I try to serialize a type like El[] where El is a class, but nothing is generated.
GeneralRe: Not working with an array of objetmemberMihai Maerean16 Feb '09 - 0:14 
I will update the article downloads with the latest version.
 


@};- Let there be love @};-

Kilroy was here

GeneralRe: Not working with an array of objetmemberMihai Maerean16 Feb '09 - 18:09 
I have sent the new Zip file to codeproject. Waiting for them to replace the file ( http://www.codeproject.com/info/submit.aspx#Update[^] )
 

GeneralRe: Not working with an array of objetmemberMihai Maerean17 Feb '09 - 18:21 
The download files have been updated.
 

GeneralJSON to HTMLmemberaggla24 Mar '08 - 2:15 
Can we use your code to pass from JSON representation of an HTMLElement ( some thing like :
 
{
"HTMLTableElement": {
"id":"MyTable",
"Width":183,
"Height":89,
"border":1
}
}

)
 
to a Javascript object HTMLElement ??
 
Thank you Smile | :)
GeneralRe: JSON to HTMLmemberMihai Maerean24 Mar '08 - 2:58 
Classes in Javascript are, basically, HashTables with member names as strings for the keys in the HashTable.
 
You can create objects like you said, but it will lack the entries in the HashTable corresponding to the "prototype" functions and/or other members created in the "constructor".
 
If the function that will receive the data doesn't call those functions, you can trick it to accept your data structure.
 


@};- Let there be love @};-

Kilroy was here

GeneralRe: JSON to HTMLmemberaggla24 Mar '08 - 6:34 
I see what you mean! I'm gonna try it.. Thank you so much Smile | :)
GeneralRe: JSON to HTMLmemberaggla24 Mar '08 - 9:56 
Do you know about a place where I can find good documentation about this?
GeneralWhy? Maybe an AnswermemberDewey23 Feb '08 - 17:42 
I haven't used Microsoft's implementation of a JSON parser, but I have used others.
 
It appears to me that this solution will take ANY dynamically generated, arbitrary data structure and convert it to a JSON object.
 
Most of the serializers I've see, will serialize C# defined data structures and objects, but not dynamically generated ones(please correct me if anyone knows different).
 
If that's true, then this solution solves some problems not addressed in other products.
QuestionWhy?memberstevekain23 Feb '08 - 6:17 
Why wouldn't you use the JSON serializer that is included in the AJAX Control Toolkit? Did you invent those round things between your car and the road?
AnswerRe: Why?memberSteven Berkovitz23 Feb '08 - 6:35 
I think you mean the JSON serializer (JavaScriptSerializer) that is included in the System.Web.Script.Serialization namespace.
 
-Steven

AnswerRe: Why?memberMihai Maerean23 Feb '08 - 7:54 
As it says here http://msdn2.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx[^], this class has been introduced in .Net 3.5 and didn't know about it (and it didn't even show up when I googled for it).
 
And as I said in the article, the whole point was to keep it simple to use: not to need to store a serializer and a specially written converter (e.g. System.Web.Script.Serialization.CS.ListItemCollectionConverter) and if there isn't such a converter, waste time to learn how to write one.
 
In the end, I reinvented "the wheel" because is fun to do it yourself and you can learn a lot and, when it's done, you can customize it to fit your specific needs. And others can learn a lot as well by reading the source code (which you can't in the case of the ListItemCollectionConverter and the JavaScriptSerializer).
 


@};- Let there be love @};-

Kilroy was here

GeneralRe: Why?memberAVAUX15 Feb '09 - 22:55 
You forget DataContractJsonSerializer too Wink | ;)
GeneralRe: Why?memberdojohansen20 Feb '09 - 4:10 
I also didn't know about this one. Is there a compiled option so reflection is used only the first time an instance of a particular type is serialized?
AnswerRe: Why?memberMihai Maerean23 Feb '08 - 8:11 
And there's another issue: I've been working with Microsoft technologies for 10 years now and, lately, I find it very hard to keep up with them. Microsoft is developing technologies at such a rapid pace, I don't have the time to keep myself up to date on everything they do.
The college is over and the time for studying is limited. That's why I missed the class they introduced in their latest .net release, but I'm very proud that I stumbled upon them same problem as they did and managed to come with a solution that (I consider) is even easier to use. Maybe not as general purpose as their solution, but easier to use in 90% of the cases where you want to send data to the Javascript client code. Have you noticed that all examples of all JSON engines are about serializing to a stream (file) and never to actually send it to Javascript and teach you how to create the javascript object from that JSON string? Because that's what JSON (JavaScript Object Notation) was created for.
 


@};- Let there be love @};-

Kilroy was here

GeneralRe: Why?memberCitizenDC19 Mar '08 - 0:04 
Thank you for sharing your code mate! Wink | ;)
GeneralRe: Why?memberMihai Maerean19 Mar '08 - 0:09 
You're welcome.
 
I learned a lot by writing it.
 
Hope it helps.
 


@};- Let there be love @};-

Kilroy was here

AnswerRe: Why?memberJamie Nordmeyer18 Feb '09 - 2:39 
Don't know why people like you feel the need to jump to sarcasm so quick, instead of giving constructive feedback.
 
Maybe he hadn't heard of the one from the AJAX control toolkit. Maybe he wanted it for a non-ajax application. Maybe he didn't like that version, so he wrote his own. Or maybe he really just wanted to figure out the concepts for himself. Do you know how many programmers wrote their own String class back in the C++ days? We all knew that MFC and the STL provided these already, but most of us wrote our own at some point to get down the fundamentals of how it works.
 
Jamie Nordmeyer
Portland, Oregon, USA

http://www.feralcodemonkies.com

AnswerRe: Why?memberdojohansen20 Feb '09 - 4:13 
If this was intended to be funny, it wasn't very successful. And if it wasn't supposed to be funny, what a smallminded jerk you are!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 17 Feb 2009
Article Copyright 2008 by Mihai Maerean
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid