Summary: How do I map a field name in JSON data to a field name of a .Net object when using JavaScriptSerializer.Deserialize ?
Longer version: I have the following JSON data coming to me from a server API (Not coded in .Net)
{"user_id":1234, "detail_level":"low"}
I have the following C# object for it:
[Serializable]
public class DataObject
{
[XmlElement("user_id")]
public int UserId { get; set; }
[XmlElement("detail_level")]
public DetailLevel DetailLevel { get; set; }
}
Where DetailLevel is an enum with "Low" as one of the values.
This test fails:
[TestMethod]
public void DataObjectSimpleParseTest()
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
DataObject dataObject = serializer.Deserialize<DataObject>(JsonData);
Assert.IsNotNull(dataObject);
Assert.AreEqual(DetailLevel.Low, dataObject.DetailLevel);
Assert.AreEqual(1234, dataObject.UserId);
}
And the last two asserts fail, since there is no data in those fields. If I change the JSON data to
{"userid":1234, "detaillevel":"low"}
Then it passes. But I can't change the server's behaviour, and I want the client classes to have well-named properties in the C# idiom. I can't use LINQ to JSON since I want it to work outside of Silverlight. It looks like the XmlElement tags are having no effect. I don't know where I got the idea they were relevant at all, they probably aren't.
How do you do field name mapping in JavaScriptSerializer? Can it be done at all?
There is no standard support for renaming properties in
JavaScriptSerializer
however you can quite easily add your own:The
DataObject
class then becomes:I appreicate this might be a little late but thought other people wanting to use the
JavaScriptSerializer
rather than theDataContractJsonSerializer
might appreciate it.By creating a custom JavaScriptConverter you can map any name to any property. But it does require hand coding the map, which is less than ideal.
Then you can deserialize like so:
My requirements included:
My solution in the end was to use SimpleJson(https://github.com/facebook-csharp-sdk/simple-json).
Although you can install it via a nuget package, I included just that single SimpleJson.cs file (with the MIT license) in my project and referenced it.
I hope this helps someone.
I have used the using Newtonsoft.Json as below. Create an object:
Now Call the below method to serialize to Json object as shown below.
For those who don't want to go for Newtonsoft Json.Net or
DataContractJsonSerializer
for some reason (I can't think of any :) ), here is an implementation ofJavaScriptConverter
that supportsDataContract
andenum
tostring
conversion -Note: This
DataContractJavaScriptConverter
will only handleDataContract
classes defined in the assembly where it is placed. If you want classes from separate assemblies, modify the_supportedTypes
list accordingly in the static constructror.This can be used as follows -
The
DataObject
class would look like this -Please note that this solution doesn't handle
EmitDefaultValue
andOrder
properties supported byDataMember
attribute.I took another try at it, using the DataContractJsonSerializer class. This solves it:
The code looks like this:
And the test is:
The only drawback is that I had to change DetailLevel from an enum to a string - if you keep the enum type in place, the DataContractJsonSerializer expects to read a numeric value and fails. See DataContractJsonSerializer and Enums for further details.
In my opinion this is quite poor, especially as JavaScriptSerializer handles it correctly. This is the exception that you get trying to parse a string into an enum:
And marking up the enum like this does not change this behaviour:
This also seems to work in Silverlight.