JSON Serialization Using C# 3.0 Extension Methods

I had just been playing around with C# 3.0 extension methods when Scott Hanselman posted this article about easy JSON object serialization in Ruby.  That got me thinking that with .NET Reflection and C# 3.0 extension methods, this should be easy to do in C#.  Here is what I came up with:
using System;
using System.Text;
using System.Reflection;
namespace KeithHill.CSharpExtensionMethodSample {
  public class Person {
    public string firstName = "Scott";
    public string lastName = "Hanselman";
    public DateTime birthDay = DateTime.Parse("1:1:0 1/15/1970");
    public decimal moneyInPocket = 4.5M;
  }
  class Program {
    static void Main(string[] args) {
      Person person = new Person();
      Console.WriteLine(person.ToJavaScriptObjectNotation());
    }
  }
  public static class JsonExtension {
    public static string ToJavaScriptObjectNotation(this object obj) {
      var strBld = new StringBuilder("{");
      Type objType = obj.GetType();
      bool firstIter = true;
      foreach (FieldInfo fieldInfo in
objType.GetFields(BindingFlags.Public | BindingFlags
.Instance)) {
        if (!firstIter) strBld.Append(", ");
        strBld.AppendFormat("\"{0}\":{1}", fieldInfo.Name,
GetJsonStringForFieldValue(fieldInfo, obj));
        firstIter = false;
      }
      strBld.Append("}");
      return strBld.ToString();
    } 
    private static string GetJsonStringForFieldValue(FieldInfo field, object obj) {
      string val;
      string typeName = field.FieldType.FullName;
      switch (typeName) {
        case "System.DateTime":
          TimeSpan ts = (DateTime)field.GetValue(obj) - DateTime.Parse("1/1/1970");
          val = " new Date(" + ts.TotalMilliseconds.ToString() + ")";
          break
        case "System.String":
          val = "\"" + (string)field.GetValue(obj) + "\"";
          break
        default:
          val = field.GetValue(obj).ToString();
          break;
      }
      return val;
    }
  }
Now this is by no means bullet proof.  Heck I only spent about 15 minutes on it and most of that time was figuring out how the heck to convert a .NET DateTime to a JavaScript Date value.  Anyway the output looks like this:
 
{"firstName":"Scott", "lastName":"Hanselman",
 "birthDay": new Date(1213260000), "moneyInPocket":4.5}
This entry was posted in LINQ. Bookmark the permalink.

6 Responses to JSON Serialization Using C# 3.0 Extension Methods

  1. Michael says:

    How can I compile this code?

  2. Keith says:

    Michael, you need to download the May CTP LINQ bits.  Those bits contain the early preview of the C# 3.0 compiler that supports extension methods.  The bits can be downloaded here:
     
    http://www.microsoft.com/downloads/details.aspx?FamilyID=1E902C21-340C-4D13-9F04-70EB5E3DCEEA&displaylang=en

  3. Addy says:

    I just ran across Scott Hanselman\’s post and had the same idea of leveraging extension methods… Luckily I googled first before coding 🙂
     
    You might want to plug a \’real\’ JSON serializer (such as Atlas) into the extension method to support more nested or more complex datatypes, etc.  The code as it stands is a great proof of concept but isn\’t really robust enough for real world scenarios.

  4. Keith says:

    Addys, I really don\’t know enough about JSON to go much further.  I just thought, like you did, that C# 3.0 extension methods should enable this scenario.

  5. Matthew says:

    It\’s even easier now using the DataContractJsonSerializer class…
     

    public static string ToJSON( this object obj )
    {
    string json = string.Empty;
    DataContractJsonSerializer ser = new DataContractJsonSerializer(obj.GetType());
    using ( MemoryStream ms = new MemoryStream() )
    {
    ser.WriteObject(ms, obj);
    json = Encoding.Default.GetString(ms.ToArray());
    }
    return json;
    }
    And to get back…
    public static T FromJSON<T>( this string json )
    {
    using ( MemoryStream ms = new MemoryStream(ASCIIEncoding.Default.GetBytes(json)) )
    {
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
    return (T)ser.ReadObject(ms);
    }
    }

  6. Keith says:

    That\’s a new feature in WCF in .NET 3.5, right?  I\’ll have to look into that.  Thanks for the sample code!

Leave a reply to Keith Cancel reply