Json.NET常用方法匯總(可解決日常百分之90的需求)
0.Json.NET基礎用法
首先去官網下載最新的Newtonsoft.Json.dll(也可以使用VS自帶的NuGet搜索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);
}
}
}
結果:

- (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(); } }
結果為:

有時候會有這樣的需求,序列化出的屬性值均要為字串格式,即要將上圖結果的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());
}
}
使用方法同上例,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/112667.html
標籤:C#
