Newtonsoft.Json高级用法

Newtonsoft.Json介绍

在做开发的时候,很多数据都是以Json格式传输的,而使用Json的时候,我们通常会涉及到几个序列化对象的使用:

  • System.Runtime.Serialization.Json.DataContractJsonSerializer
  • System.Web.Script.Serialization.JavaScriptSerializer
  • Json.NET即Newtonsoft.Json
    由于Json.NET的性能及通用性较好,因此它的使用范围越来越广,借助前人的经验今天我也总结使用一下。
    官网API:http://www.newtonsoft.com/json/help/html/N_Newtonsoft_Json.htm

基本用法

Json.Net是支持序列化和反序列化DataTable、DataSet、Entity Framework和Entity的

private void Newtonsoft()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("Name", Type.GetType("System.String"));
    dt.Columns.Add("Sex", Type.GetType("System.String"));
    dt.Columns.Add("Age", Type.GetType("System.Int32"));
    dt.Columns.Add("PhoneNumber", Type.GetType("System.String"));
    for (int i = 0; i < 3; i++)
    {
        DataRow dr = dt.NewRow();
        dr["Name"] = "Name" + i;
        dr["Sex"] = i % 2 == 0 ? "女" : "男";
        dr["Age"] = 18 + i;
        dr["PhoneNumber"] = "18233388888";
        dt.Rows.Add(dr);
    }
    /*序列化DataTable*/
    string json = JsonConvert.SerializeObject(dt);
    /*反序列化DataTable*/
    DataTable dtSource = JsonConvert.DeserializeObject<DataTable>(json);
    foreach (DataRow item in dtSource.Rows)
    {
        string name = item["Name"].ToString();
        string sex = item["Sex"].ToString();
        int age = int.Parse(item["Age"].ToString());
        string phoneNumber = item["PhoneNumber"].ToString();
    }
}

DataSet、Entity Framework序列化和DataTable一样,这里就不过多介绍了。
序列化之后结果如下:
序列化之后

不创建新类型对json字符串反序列化

可以利用JObject 对象实现通过[]来读取对象中的属性的功能。

private void TestHttpHelper()
{
    string url = "http://openapi.tencentyun.com/v3/user/get_info";
    string data = "openid=B624064BA065E01CB73F835017FE96FA&" +
                  "openkey=5F154D7D2751AEDC8527269006F290F70297B7E54667536C&" +
                  "appid=2&" +
                  "sig=VrN%2BTn5J%2Fg4IIo0egUdxq6%2B0otk%3D&" +
                  "pf=qzone&" +
                  "format=json&" +
                  "userip=112.90.139.30";
    string result = HttpHelper.HttpGet(url + "?" + data);    
    JObject obj = JsonConvert.DeserializeObject<JObject>(result);
    int int1 = Convert.ToInt32(obj["ret"]);
    string str1 = obj["msg"].ToString();
}

高级用法

  1. 忽略某些属性
  2. 默认值的处理
  3. 空值的处理
  4. 支持非公共成员
  5. 日期处理
  6. 自定义序列化的字段名称
  7. 动态决定属性是否序列化

一、忽略某些属性
实体类中有很多属性,根据实际情况有些属性不需要序列化返回,可以使用该特性。首先介绍Json.Net序列化的模式:OptOut和OptIn

参数解释
OptOut默认值,类中所有公共成员都会被序列化,如果不想被序列化,可以加特性JsonIgnore
OptIn默认情况下,所有成员都不会被序列化,类中的成员只有加特性Json Property才会被序列化,当类的成员很多,但客户端仅仅需要一部分数据时很有用

只有Name和PhoneNumber

[JsonObject(MemberSerialization.OptIn)]
public class Person
{
    [JsonProperty]
    public string Name { get; set; }
    public string Sex { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    [JsonProperty]
    public string PhoneNumber { get; set; }
}

这里写图片描述
不要性别、住址、手机号

[JsonObject(MemberSerialization.OptOut)]
public class Person
{
    public string Name { get; set; }
    [JsonIgnore]
    public string Sex { get; set; }
    public int Age { get; set; }
    [JsonIgnore]
    public string Address { get; set; }
    [JsonIgnore]
    public string PhoneNumber { get; set; }
}

这里写图片描述
二、默认值处理
序列化时想忽略默认值属性可以通过JsonSerializerSettings.DefaultValueHanding来设置,该值为枚举值

参数解释
DefaultValueHanding.Ignore序列化和反序列化时,忽略没赋值的属性
DefaultValueHanding.Include序列化和反序列化时,包含没赋值的属性
public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}

忽略没有赋值的属性:
这里写图片描述
包含没有赋值的属性:
这里写图片描述
三、空值的处理
序列化时需要忽略值为NULL的属性,可以通过JsonSerializerSettings.NullValueHanding来设置,另外用JsonSerializerSettings设置属性是对序列化过程中所有属性生效的,想单独对某一个属性生效可以使用JsonProperty,下面将展示两种方式。
1、JsonSerializerSettings方式
忽略值为NULL的属性:
int类型属性默认值为0,string类型属性默认值为null
这里写图片描述
包含值为NULL的属性:
这里写图片描述
2、JsonProperty方式
当Address值为NULL时忽略:

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public int Age { get; set; }
    [JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}

这里写图片描述
四、支持非公共成员
序列化时默认都是只处理公共成员,如果需要处理非公共成员,就要在该成员上加特性”JsonProperty”。
private不加JsonProperty:

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
    private int Wife { get; set; }
    public Person()
    {
        Wife = 3;
    }
}

这里写图片描述
private加JsonProperty:

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
    [JsonProperty]
    private int Wife { get; set; }
    public Person()
    {
        Wife = 3;
    }
}

这里写图片描述
五、日期处理
DateTime类型属性的处理稍微麻烦点,系统默认格式化为iso日期标准,

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public DateTime Birthday { get; set; }
}

这里写图片描述

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime Birthday { get; set; }
}

但实际使用过程中大多数使用的可能是yyyy-MM-dd或yyyy-MM-dd HH:mm:ss这两种格式的日期,解决办法可以是将DateTime类型转成string类型自己先格式化然后再序列化。其次,Json.Net提供了IsoDateTimeConvert日期转换这个类,可以通过JsonConverter实现相应的日期转换,效果跟不加JsonConverter是一样的,在此就不截图了,但这明显不是我们想要的结果,我们可以继承该类实现自己的日期格式

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    [JsonConverter(typeof(ChinaDateTimeConcerter))]
    public DateTime Birthday { get; set; }
}
public class ChinaDateTimeConcerter : DateTimeConverterBase
{
    private static IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" };
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return dtConverter.ReadJson(reader, objectType, existingValue, serializer);
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        dtConverter.WriteJson(writer, value, serializer);
    }
}

这里写图片描述
这样自己就实现了一个yyyy-MM-dd日期格式化转换类,如果需要yyyy-MM-dd HH:mm:ss日期格式自己也可以很容易实现了。
六、自定义序列化字段的名称
实体类中定义的属性名可能不是自己想要的名称,但是不能更改实体定义,这个时候可以自定义序列化字段的名称。

public class Person
{
    public string Name { get; set; }
    [JsonProperty(PropertyName = "MySex")]
    public string Sex { get; set; }
    [JsonProperty(PropertyName = "MyAge")]
    public int Age { get; set; }
} 

序列化后:
这里写图片描述
反序列化后:
这里写图片描述

七、动态决定属性是否序列化
在某些场景下,可能A场景输出A、B、C三个属性,B场景输出C,D,E三个属性,Json.Net支持此种非常规的特性。
继承默认的DefaultContractResolver类,传入需要的属性:

public class Person
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}
public class LimitPropsContractResolver : DefaultContractResolver
{
    string[] props = null;
    public LimitPropsContractResolver(string[] props)
    {
        //指定要序列化属性的清单
        this.props = props;
    }
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
        //只保留清单列出的属性
        return list.Where(p => props.Contains(p.PropertyName)).ToList();
    }
}

使用自定义解析类,只输出Name、Sex、Age三个属性
这里写图片描述

总结

Newtonsoft.Json序列化库替我们想了很多特性,也实现了很多特性,除了上面介绍的几种高级用法外,还有其它的特殊用法,可以去官网进行学习,我在学会了使用Newtonsoft.Json之后,非常想知道其内部是如何实现特性这一功能的,不知道大家有何感想。
官网示例代码地址:http://www.newtonsoft.com/json/help/html/DefaultValueHandlingIgnore.htm

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

changuncle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值