环境:
- .net core3.1
- vs2019
- Newtonsoft.Json 12.0.3
关于newtonsoft.json的使用常见问题参考:
《c#:序列化json常见问题及处理方法》
《c#:关于NewtonsoftJson序列化和Grpc序列化的冲突问题》
问题:如何在不新建类的情况下动态解析json字符串?
如下面:
{
"Color": {
"Red": 0.8,
"Blue": 1.2
},
"Category": {
"Better": [ 99, 98, 100, 96 ],
"Normal": [ 80, 75, 84 ]
}
}
问: 为什么不能使用指定的类进行反序列化?
答: json中的格式不能完全确定,可能是为将来保留,或者是供别人使用,而自己只负责读写其中的一块,如:“$.Color”
下面的代码就演示如何动态解析这个json字符串:
static void TestReadJson()
{
var json = @"
{
""Color"": {
""Red"": 0.8,
""Blue"": 1.2
},
""Category"": {
""Better"": [ 99, 98, 100, 96 ],
""Normal"": [ 80, 75, 84 ]
}
}";
JObject obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(json);
//color_red=0.8
var color_red = obj["Color"]["Red"].Value<decimal>();
//color_blue=1.2
var color_blue = obj["Color"]["Blue"].Value<double>();
//other ==null true
var other = obj["Color:NotExsit"];
Console.WriteLine($"other==null => {other == null}");
//d = 99
var d = obj["Category"]["Better"][0].Value<int>();
//遍历所有属性
var propNameList = new List<string>();
var propValueList = new List<double>();
var props = (obj["Color"] as JObject).Properties();
foreach (var prop in props)
{
propNameList.Add(prop.Name);
propValueList.Add(prop.Value.Value<double>());
}
//propNameList=Red,Blue
//propValueList=0.8,1.2
//遍历数组所有元素
var values = new List<int>();
var arr = obj["Category"]["Better"] as JArray;
foreach (var item in arr)
{
values.Add(item.Value<int>());
}
//values=99, 98, 100, 96
}
问题: 如何在不新建类的情况下动态组装json?
上面只说了动态解析,那么还有动态组装json的情况,如下面的json:
{
"Color": {
"Red": 0.8,
"Blue": 1.2
},
"Category": {
"Better": [ 99, 98, 100, 96 ],
"Normal": [ 80, 75, 84 ],
"Bad": [undefined,null]
}
}
看下面的代码:
static void TestCreateJson()
{
/* 手动组装json
{
"Color": {
"Red": 0.8,
"Blue": 1.2
},
"Category": {
"Better": [ 99, 98, 100, 96 ],
"Normal": [ 80, 75, 84 ],
"Bad": [undefined,null]
}
}
*/
//写入JObject
//创建json字符串根节点
var obj = new JObject(); //{}
//Color节点
obj["Color"] = new JObject();// { "Color" : {} }
obj["Color"]["Red"] = 0.8;// { "Color" : { "Red" : 0.8 } }
obj["Color"]["Blue"] = 1.2;// { "Color" : { "Red" : 0.8 , "Blue" : 1.2 } }
//Category节点
obj["Category"] = new JObject();// { "Color" : { "Red" : 0.8 , "Blue" : 1.2 }, "Category": {} }
//Category->Better数组
obj["Category"]["Better"] = new JArray();
(obj["Category"]["Better"] as JArray).Add(99);
(obj["Category"]["Better"] as JArray).Add(98);
(obj["Category"]["Better"] as JArray).Add(100);
(obj["Category"]["Better"] as JArray).Add(96); //{ "Color" : { "Red" : 0.8 , "Blue" : 1.2 }, "Category": { “Better”: [99, 98, 100, 96] } }
//Category->Normal数组
obj["Category"]["Normal"] = new JArray();
(obj["Category"]["Normal"] as JArray).Add(80);
(obj["Category"]["Normal"] as JArray).Add(75);
(obj["Category"]["Normal"] as JArray).Add(84);//{ "Color" : { "Red" : 0.8 , "Blue" : 1.2 }, "Category": { “Better”: [99, 98, 100, 96], “Normal”: [80, 75, 84] } }
//Category->Bad数组
obj["Category"]["Bad"] = new JArray();
(obj["Category"]["Bad"] as JArray).Add(JValue.CreateUndefined());
(obj["Category"]["Bad"] as JArray).Add(JValue.CreateNull());//{ "Color" : { "Red" : 0.8 , "Blue" : 1.2 }, "Category": { “Better”: [99, 98, 100, 96], “Normal”: [80, 75, 84], "Bad": [ undefined, null ] } }
//输出json
var jsonStr = obj.ToString();
}
问题: 如何在不新建类的情况下改写json?
既然上面有了动态解析和组装,那么就有改写部分json的需求,看如下代码:
static void TestUpdateJson()
{
var json = @"
{
""Color"": {
""Red"": 0.8,
""Blue"": 1.2
},
""Category"": {
""Better"": [ 99, 98, 100, 96 ],
""Normal"": [ 80, 75, 84 ],
""Bad"": [undefined,null]
}
}";
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(json);
obj["Color"] = "Red,Blue";
obj["Category"]["Better"][0] = 100;
obj["Category"]["Normal"][0] = new JObject();
json = obj.ToString();
/*
{
"Color": "Red,Blue",
"Category": {
"Better": [100,98,100,96],
"Normal": [{},75,84],
"Bad": [null,null]
}
}
*/
}
问题: 如何动态删除json里的内容?
直接看代码:
static void TestDeleteJson()
{
var json = @"
{
""Color"": {
""Red"": 0.8,
""Blue"": 1.2
},
""Category"": {
""Better"": [ 99, 98, 100, 96 ],
""Normal"": [ 80, 75, 84 ],
""Bad"": [undefined,null]
}
}";
//移除属性和数组元素
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(json);
(obj["Color"] as JObject).Remove("Red");
(obj["Category"] as JObject).Remove("Better");
obj["Category"]["Normal"][0].Remove();
json = obj.ToString();
/*
{
"Color": {
"Blue": 1.2
},
"Category": {
"Normal": [80,75,84],
"Bad": [null,null]
}
}
*/
}
问题:用考虑json文件中的注释吗?
用!!!
因为,我们现在是将json读取到JArray/JObject,Newtonsoft.Json 会将注释一并读取到结构,所以我们要手动排除注释的干扰,具体可参考:
《Newtonsoft.Json 反序列化注意点》