为Json对象生成的C#类的优点和缺点

时间:2012-02-10 14:22:13

标签: c# asp.net json serialization code-generation

我有Json示例,我需要将其序列化为C#对象。我决定利用这个目的Json.Net库。另外我需要有代表这个Json的C#类。要创建类,可以使用Json C# class generator。我们有两种选择。 “创建属性”和生成的类将如下所示:

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"));
        }
    }
}

另一个选项是“生成预先填充的只读字段”,类看起来像

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;
}

这两个生成的类都依赖于JObject和JsonClassHelper。但这些类不能与JsonSerializer一起使用,如

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

我们可以使用JObject.Load方法

创建这些类的对象
var ro = new RootObject(Newtonsoft.Json.Linq.JObject.Load(reader));

另一种方法是使用在线json2csharp转换器,类看起来像

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可以处理这个类。

我的问题是什么类生成器更适合使用,使用每种类型的生成类有什么好处和缺点? 谢谢你的建议。

3 个答案:

答案 0 :(得分:3)

我假设您要将json字符串反序列化为c#对象。我通常自己创建C#对象,并使用JsonConvert反序列化json字符串。

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; }
}

答案 1 :(得分:3)

如果您知道要返回的对象类型,请查看在4.0 Framework中使用System.Runtime.Serialization.Json命名空间。它的很多比JSON.NET更容易使用。事实上,它可能是最简单的替代品。

在包含对此命名空间的引用(以及使用语句)之后,您需要使用 [DataContract] 属性标记您的类,并使用 [DataMember] 属性。然后,您可以使用像这样的通用例程:

/// <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;
        }
    }       
}

这就是它的全部内容。

答案 2 :(得分:2)

我从不使用类生成器。当课程很少时,我会手动编码。当反序列化过程需要很多类时,我更喜欢使用dynamic对象,并将其用作here,这使代码更具可读性。

以下是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);
}