Implicit Conversions and LINQ to JSON

I have been doing a lot of work with Json.NET recently and have really been using LINQ to JSON in anger for the first time.

Pretty quickly I became annoyed with having to constantly wrap .NET primitive objects (int, long, string, DateTime, etc) in JValue whenever they’re added to a JSON object or array.

JObject moss = new JObject();
moss["FirstName"] = new JValue("Maurice");
moss["LastName"] = new JValue("Moss");
moss["BirthDate"] = new JValue(new DateTime(1977, 12, 30));
moss["Department"] = new JValue("IT");
moss["JobTitle"] = new JValue("Support");
 
Console.WriteLine(moss.ToString());
//{
//  "FirstName": "Maurice",
//  "LastName": "Moss",
//  "BirthDate": "\/Date(252241200000+1300)\/",
//  "Department": "IT",
//  "JobTitle": "Support"
//}

Gross. Why?

For all the LINQy goodness I’ve added to Json.NET to work everything has to inherit from a common object: JToken. Container objects (JObject and JArray) inherit from JToken and all their child values must also be JTokens. For that reason JObject implements IDictionary<string, JToken> and JArray implements IList<JToken>.

Because the containers only allow JTokens, basic primitive values need to be wrapped in an object which inherits from JToken: JValue.

Each time we want to set a value on an object or add a value to an array it has to be manually wrapped in a JValue. Ugly!

Implicit Conversions

The solution is really simple: implicit conversions. Adding an implicit conversion operator allows .NET to automatically convert from the primitive to JValue without any of the above unpleasantness.

///<summary>
/// Performs an implicit conversion from <see cref="String"/> to <see cref="JToken"/>.
///</summary>
///<param name="value">The value to create a <see cref="JValue"/> from.</param>
///<returns>The <see cref="JValue"/> initialized with the specified value.</returns>
public static implicit operator JToken(string value)
{
  return new JValue(value);
}

And here is the new end user experience:

JObject jen = new JObject();
jen["FirstName"] = "Jen";
jen["LastName"] = "Barber";
jen["BirthDate"] = new DateTime(1978, 3, 15);
jen["Department"] = "IT";
jen["JobTitle"] = "Manager";

Much better I think you’ll agree. I only wish I had done it earlier [:)]