环境:
- .net 6.0
- Newtonsoft.Json 12.0.3
1. Newtonsoft.Json 反序列化时对注释的不同处理
在json文件中,我们常常需要有注释行,如下:
[
{
"name": "tom",
"age": 18,
"birth": "1998-02-01" /*,
"score:":98.5,*/
//"ref":null,
//"desc":undefined
},
/*{
"name": "jack",
"age": 20
},*/
{
"name": "lisa",
"age": 16
}
]
Newtonsoft.Json
在反序列化时,对于不同的反序列化目的对象,对注释的处理方式不同,具体来说:
- 当我们反序列化到
JArray
或JObject
的时候,它会正常读取注释并作为一项; - 当我们反序列化到自定义实体类的时候,它会忽略注释;
2. 实例演示不同的处理方式
就以上面的json文件来说,看看Newtonsoft.Json
处理的结果:
internal class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText("appsettings.json", Encoding.UTF8);
var list = JsonConvert.DeserializeObject<List<Person>>(json);
var str = $"list.Count={list.Count}\r\n[{string.Join("\r\n", list.Select(i => i))}]";
Console.WriteLine("Hello World!");
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public float Score { get; set; }
public int Age { get; set; }
public DateTime Birth { get; set; }
public object Ref { get; set; }
public string Desc { get; set; }
public override string ToString()
{
return $"{{Id={Id},Name={Name},Score={Score},Age={Age},Birth={Birth},Ref={Ref},Desc={Desc}}}";
}
}
效果如下:
可以看到,json文件中的注释并不会对结果产生影响。
不过当我们序列化为JArray的时候,再看看:
internal class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText("appsettings.json", Encoding.UTF8);
var array = JsonConvert.DeserializeObject<JArray>(json);
var str = $"array.Count={array.Count},arr[1].Type={array[1].Type},arr[1]={array[1]}";
Console.WriteLine("Hello World!");
}
}
效果如下:
可以看到,反序列化的对象是JArray(或者是JToken)的时候,注释也是被当成一项加载到结构中的。
所以,我们在用JObject/JArray动态解析Json的时候要特别注意了。
3. 如何在反序列化到JArray或JToken的时候忽略掉注释
直接上代码:
internal class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText("appsettings.json", Encoding.UTF8);
var array = JArray.Parse(json, new JsonLoadSettings
{
CommentHandling = CommentHandling.Ignore,
});
var str = $"array.Count={array.Count},arr[0].Type={array[0].Type},arr[1].Type={array[1].Type}";
Console.WriteLine("Hello World!");
}
}
效果如下:
4. 从源码观察Newtonsoft.Json对注释的不同处理
就简单的看下源码,Newtonsoft.Json 对目标是JToken(JObject/JArray继承自JToken)和其他自定义类的处理逻辑不同。
对于自定义的实体类,Newtonsoft.Json 最终会调用PopulateObject方法去组装对象,它的源码如下:
再看看反序列到JArray时的处理: