欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【Json】1.Newtonsoft—Json.NET常用方法简述

程序员文章站 2022-06-29 08:53:01
Json.NET常用方法汇总(可解决日常百分之90的需求) 0.Json.NET基础用法 首先去官网下载最新的Newtonsoft.Json.dll(也可以使用VS自带的NuGet搜索Json.NET下载(下载下图第二个))并引用至项目。 (1)序列化实体类(将实体类对象序列化为Json字符串) 结 ......


 

json.net常用方法汇总(可解决日常百分之90的需求)

 

0.json.net基础用法


   首先去官网下载最新的newtonsoft.json.dll(也可以使用vs自带的nuget搜索json.net下载(下载下图第二个))并引用至项目。

  【Json】1.Newtonsoft—Json.NET常用方法简述

  • (1)序列化实体类(将实体类对象序列化为json字符串)
using system;
using newtonsoft.json;

namespace json_net_test
{
    /// <summary>
    /// 定义一个实体类
    /// </summary>
    public class student
    {
        public string name;
        public int age;
        public string class;
    }
    class program
    {
        static void main(string[] args)
        {
            //创建实体类对象           
            student stu = new student
            {
                name = "老王",
                age = 99,
                class = "三班"
            };
            //开始序列化
            string jsonstr = jsonconvert.serializeobject(stu, formatting.indented);
            console.writeline(jsonstr);
        }
    }
}

  结果:

  【Json】1.Newtonsoft—Json.NET常用方法简述

  • (2)反序列化(将json字符串反序列化为实体类对象)
using system;
using newtonsoft.json;

namespace json_net_test
{
    /// <summary>
    /// 定义一个实体类
    /// </summary>
    public class student
    {
        public string name;
        public int age;
        public string class;
    }
    class program
    {
        static void main(string[] args)
        {
            //json字符串
            string jsonstr = "{\"name\": \"老王\",\"age\": 99,\"class\": \"三班\"}";
            //开始反序列化
            student stu = jsonconvert.deserializeobject<student>(jsonstr);
        }
    }
}

 

1.序列化与反序列化时忽略某些属性


  •  (1)忽略类内所有属性

  [jsonobject(memberserialization.optin)]用于在序列化与反序列化时忽略一个类里所有的属性,只有当在类内属性上打特性标签[jsonproperty]时才支持序列化与反序列化。所以[jsonobject(memberserialization.optin)]常用于与[jsonproperty]配合使用。

  例:

[jsonobject(memberserialization.optin)]
public class person
{
    public int age { get; set; }

    [jsonproperty]
    public string name { get; set; }

    public string sex { get; set; }

    public bool ismarry { get; set; }

    public datetime birthday { get; set; }
}

 

  • (2)序列化所有属性(默认)

  默认实体类上默认打着[jsonobject(memberserialization.optout)]特性标签(可以省略不写),如果要忽略某些属性,要在属性上打[jsonignore]。

  例:

[jsonobject(memberserialization.optout)]
public class person
{
    public int age { get; set; }

    public string name { get; set; }

    public string sex { get; set; }

    [jsonignore]
    public bool ismarry { get; set; }

    public datetime birthday { get; set; }
}

 

  • (3)动态控制实体类属性的是否忽略序列化(默认)

  当某些条件下需要序列化a属性和b属性,某些情况下需要忽略a属性与b属性,我们该怎么做?
  答:使用jsonserializersettings设置某实体类对象要忽略序列化的属性(配合if与else控制属性的动态忽略)。

  例:以下方式忽略p对象的age属性与ismarry属性:

  jsonserializersettings jsetting=new jsonserializersettings();
  jsetting.contractresolver = new limitpropscontractresolver(new string[] { "age", "ismarry" });
  console.writeline(jsonconvert.serializeobject(p, formatting.indented, jsetting));

 

2.默认值处理


  •  (1)设置属性默认值

  在属性上打 [defaultvalue("xxx")]

 

3.空值处理


  •  (1)不序列化为null的属性(使用jsonserializersettings方式)
    person p = new person 
    { 
         room = null,
         age = 10, 
         name = "张三丰", 
         sex = "男", 
         ismarry = false, 
         birthday = new datetime(1991, 1, 2) 
    };
    jsonserializersettings jsetting=new jsonserializersettings();
    jsetting.nullvaluehandling = nullvaluehandling.ignore;
    console.writeline(jsonconvert.serializeobject(p, formatting.indented, jsetting));

  ps:使用这种方式可能bool为false的也无法序列,最后的结果只包含birthday、sex、name、age。

 

  • (2)不序列化为null的属性(使用特性标签方式)
[jsonproperty(nullvaluehandling=nullvaluehandling.ignore)]
public room room { get; set; }

 

4.序列化私有成员


   因为默认只序列化public的成员,所以如果想序列化private成员,要在实体类的属性上打[jsonproperty]标签。

[jsonproperty]
private int height { get; set; }

 

5.自定义序列化名称


   在序列化与反序列化时可以自定义序列化出字符串的属性名称,如下代码可以将实体类的name属性序列化为cname属性,并且可以将json中的cname反序列化为当前实体类的name属性。(双向)

[jsonproperty(propertyname = "cname")]
public string name { get; set; }

 

6.日期处理


  • (1)解决方案1:在可以动model代码的情况下

  系统自带的datetime会格式化成iso日期标准,但是实际使用过程中大多数使用的可能是yyyy-mm-dd 或者yyyy-mm-dd hh:mm:ss两种格式的日期,解决办法是可以将datetime类型改成string类型自己格式化好,然后在序列化。
  例:

    [jsonproperty(propertyname = "starttime")]//因为默认只序列化public属性,所以要打上jsonproperty标签并且声明名称
    private string m_starttime{get;set;}

    [jsonignore]//这个标签用于在序列化与反序列化时忽略starttime属性
    public datetime starttime
    {
        get{ return convert.todatetime(m_starttime); }
        set
        {
            datetime time = value;
            m_starttime = time.tostring("yyyy-mm-dd");//这里写自己想要的格式
        }
    }

  ps:代码思路是不去序列化starttime属性,而去序列化string类型的m_starttime属性(m_starttime相当于starttime属性的私有字段)。

 

  • (2)解决方案2:使用datetimeconverterbase

  json.net提供了isodatetimeconverter日期转换这个类,可以通过jsnconverter实现相应的日期转换

[jsonconverter(typeof(isodatetimeconverter))]
public datetime birthday { get; set; }

  但是isodatetimeconverter日期格式(yyyy-mm-ddthh:mm:ss)不是我们想要的,我们可以继承该类实现自己的日期
  例:

    public class chinadatetimeconverter : 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);
        }
    }

  使用方式:

[jsonconverter(typeof(chinadatetimeconverter))]
public datetime birthday { get; set; }

 

7.以驼峰命名法序列化


   有时我们会碰到这种需求,比如我们代码里实体类型的属性名称均是以大写字母开头,如name、starttime等,但是要求我们序列出的json字符串的属性名称要以小写字母开头,如name、starttime、endtime等。我们可以使用如下代码解决

jsonserializersettings setting = new jsonserializersettings();
setting.contracresolver = new camelcasepropertynamescontractresolver();
string jsonstr = jsonconvert.serializeobject(p, newtonsoft.json.formatting.indented, setting);

  这样子的话,在序列实体类对象p的属性时,属性名称将由personname转换为personname。

 

8.枚举的序列化


   枚举默认序列化为枚举的int值,如果想要序列化为枚举string值,使用如下方式

  [jsonconverter(typeof(stringenumconverter))]
  public notifytypeenum type { get; set; }

 

9.将多个数据类型序列化为1个json对象(序列化匿名类)


   有时我们有这样的需求,对方要求我们传输过去的json字符串要包含我们多个实体类型的信息,笨方法就是重新构建一个符合要求的实体类型,但是我们又更好的方法,我们可以使用匿名类,把json需要的信息均放在匿名类中,我们可以对匿名类进行序列化。

  例:

        list<model> list1 = new list<model>();
        list<model2> list2 = new list<model2>();
        string name = "名字";
        string address = "xx";
        list<string> info = new list<string>() { name, address };
        var json = new { information = info, jsonlist1 = list1, jsonlist2 = list2 }; 

  我们只需要对上面的匿名对象“json”序列化即可。

 

10.使用jsonconverter自定义属性序列化规则(json格式转换器)


  •  (1)将属性值由double类型序列化时转为字符串类型
  public class doubletostringconverter : jsonconverter
    {
        //表示反序列化时不执行该转换器
        public override bool canread => false;
        //表示序列化时执行该转换器
        public override bool canwrite => true;

        //判断执行条件(当属性的值为double类型时才使用转换器)
        public override bool canconvert(type objecttype)
        {
            return objecttype == typeof(double);
        }

        //因为public override bool canread => false;,所以不用实现反序列化时的转换方法
        public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)
        {
            throw new notimplementedexception();
        }

        /// <summary>
        /// 序列化时执行的转换
        /// </summary>
        /// <param name="writer">可以用来重写值</param>
        /// <param name="value">属性的原值</param>
        /// <param name="serializer">就是那个serializer对象</param>
        public override void writejson(jsonwriter writer, object value, jsonserializer serializer)
        {
            double v = (double)value;
            writer.writevalue(v.tostring());
        }
    }

  使用方式:

[jsonconverter(typeof(doubletostringconverter))]
public double count{get;set;}

  ps:这样子,就可以把原本序列化出的json字符串   count : 12.3   转化为   count : "12.3"
  ps:[jsonconverter(typeof(doubletostringconverter))]也可以打在类上,表示全局设置

 

  • (2)枚举转换为int字符串

  为什么要进行这样的转换呢?

  因为枚举类型在序列化时默认序列化为枚举的int类型,即如下代码:

   /// <summary>
    /// 自定义一个枚举类型
    /// </summary>
    public enum myenum
    {
        aaa = 1,
        bbb = 2,
        ccc = 3
    }
    /// <summary>
    /// 实体类(类内有一个枚举类型的属性myenumprop)
    /// </summary>
    public class person
    {
        public myenum myenumprop { get; set; }
    }
    class program
    {

        static void main(string[] args)
        {
            person p = new person() { myenumprop = myenum.ccc };
            //json字符串
            string jsonstr = jsonconvert.serializeobject(p);
            //开始反序列化
            console.writeline(jsonstr);
            console.readline();
        }
    }

  结果为:

  【Json】1.Newtonsoft—Json.NET常用方法简述

   有时候会有这样的需求,序列化出的属性值均要为字符串格式,即要将上图结果的3改为"3"。这时候就需要自定义转换了!

  代码如下:

    public class enumtointstringconverter : jsonconverter
    {
        //反序列化时不执行
        public override bool canread => false;
        //序列化时执行
        public override bool canwrite => true;

        //控制执行条件(当属性的值为枚举类型时才使用转换器)
        public override bool canconvert(type objecttype)
        {
            return objecttype == typeof(enum);
        }

        //因为public override bool canread => false;,所以不用实现反序列化时的转换方法
        public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)
        {
            throw new notimplementedexception();
        }

        /// <summary>
        /// 序列化时执行的转换
        /// </summary>
        /// <param name="writer">可以用来重写值</param>
        /// <param name="value">属性的原值</param>
        /// <param name="serializer">就是那个serializer对象</param>
        public override void writejson(jsonwriter writer, object value, jsonserializer serializer)
        {
            enum e = (enum)value;
            int v = convert.toint32(e);
            writer.writevalue(v.tostring());
        }
    }  

  使用方法同上例。