4

I have sample Json and I need to serialize it into C# objects. I decided to leverage for this purpose Json.Net library. Also I need to have C# classes which will represent this Json. To create classes could be used Json C# class generator. There we have two options. "Create properties" and generated classes will look like:

public class Address
{
    private JObject __jobject;
    public Address(JObject obj)
    {
        this.__jobject = obj;
    }
    public string street_address
    {
        get
        {
            return JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(__jobject, "street_address"));
        }
    }
    public string city
    {
        get
        {
            return JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(__jobject, "city"));
        }
    }
    public string state_province
    {
        get
        {
            return JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(__jobject, "state_province"));
        }
    }
    public string zip_postal_code
    {
        get
        {
            return JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(__jobject, "zip_postal_code"));
        }
    }
}

and another option is "Generate pre-populated read-only fields" and classes will look like

public class Address
{

    public Address(JObject obj)
    {
       this.street_address = JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(obj, "street_address"));
       this.city = JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(obj, "city"));
       this.state_province = JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(obj, "state_province"));
       this.zip_postal_code = JsonClassHelper.ReadString(JsonClassHelper.GetJToken<JValue>(obj, "zip_postal_code"));
    }

    public readonly string street_address;
    public readonly string city;
    public readonly string state_province;
    public readonly string zip_postal_code;
}

Both these generated classes rely on JObject and JsonClassHelper. But these classes could not be used with JsonSerializer like

var ro = jsonSerializer.Deserialize<RootObject>(reader);

We can create objects of these classes using JObject.Load method

var ro = new RootObject(Newtonsoft.Json.Linq.JObject.Load(reader));

Another way is to use online json2csharp converter and classes will look like

public class Address
{
    public string street_address { get; set; }
    public string city { get; set; }
    public string state_province { get; set; }
    public string zip_postal_code { get; set; }
}

JsonSerializer could deal with this class.

My question is what classes generator is preferable to use and what are benefits and drawbacks of using each type of generated classes?
Thank you for your suggestions.

paramosh
  • 2,258
  • 1
  • 15
  • 23

3 Answers3

3

I assume you want to deserialize json string to c# object. I usually create C# object by myself, and use JsonConvert to deserialize json string.

class Program {
        static void Main(string[] args)
        {
                string json = @"
                {
                        ""street_address"":""My street address"",
                        ""city"":""My City"",
                        ""state_province"":""My State Province"",
                        ""zip_postal_code"":""My Zip Postal Code"",
                }";

                Address address = JsonConvert.DeserializeObject<Address>(json);
                Console.WriteLine("Street address: {0}", address.StreetAddress);
                Console.WriteLine("City: {0}", address.City);
                Console.WriteLine("State province: {0}", address.StateProvince);
                Console.WriteLine("Zip postal code: {0}", address.ZipPostalCode);
        }
}

public class Address {
        [JsonProperty("street_address")]
        public string StreetAddress { get; set; }

        [JsonProperty("city")]
        public string City { get; set; }

        [JsonProperty("state_province")]
        public string StateProvince { get; set; }

        [JsonProperty("zip_postal_code")]
        public string ZipPostalCode { get; set; }
}
Khairuddin Ni'am
  • 823
  • 1
  • 8
  • 13
3

If you know what kind of objects you will be returning, then look at using the System.Runtime.Serialization.Json namespace in the 4.0 Framework. It's much easier to use than JSON.NET. In fact, it's probably the easiest alternative available.

After including references to this namespace (and a using statement), you need to mark up your classes with the [DataContract] attribute and each property with the [DataMember] attribute. Then, you can use a generic routine like this one:

/// <summary>
/// 
/// Generic helper class to convert JSON text to in-memory objects
/// </summary>
/// <typeparam name="T">Type of class that the text represents</typeparam>
public class JSONHandler<T> where T : class, new()
{
    /// <summary>
    /// Convert a JSON string to an in-memory object of class T.
    /// The class T must be instantiable and not static.
    /// </summary>
    /// <param name="JSONString">JSON string describing the top level object</param>
    /// <returns>Object of class T (and any dependent objects)</returns>
    public T TextToJSON(string JSONString)
    {
        //check that we aren't passing in empty text
        if (String.IsNullOrEmpty(JSONString))
        {
            return null;
        }
        else
        {
            //create a new object
            T JSONObject = new T();
            //and create a new serializer for it
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
            //create a memor stream around the text
            System.IO.MemoryStream ms = new System.IO.MemoryStream(Encoding.Unicode.GetBytes(JSONString));
            //do the conversion
            JSONObject = (T)ser.ReadObject(ms);
            //tidy up after ourselves
            ms.Close();
            //and we're done!
            return JSONObject;
        }
    }       
}

And that is all there is to it.

deadlyvices
  • 873
  • 6
  • 18
  • Thank you for your suggestion. I agree with you that it's easier to use DataContractJsonSerializer, but it also has more restrictions. e.g. format of date and time fields. Json.Net supports wider range of formats it can successfully parse. It's important, because the service will be published for 3rd party. – paramosh Feb 10 '12 at 15:27
2

I never use class generators. When there are few classes, I code them manually. When a lot of classes are needed for deserialization process, I prefer to use dynamic object, and use it as here which makes the code more readable.

Here is an example usage of dynamic json

string json = @"{Users:[{Name:'name1',Id:1},{Name:'name2',Id:2}]}";
dynamic obj = JsonUtils.JsonObject.GetDynamicJsonObject(json);
foreach (var user in obj.Users)
{
    Console.WriteLine("{0} {1}", user.Name, user.Id);
}
Community
  • 1
  • 1
L.B
  • 114,136
  • 19
  • 178
  • 224