c#: Newtonsoft.Json 高级用法一(不创建类,动态解析和构造json、JObject/JArray)

环境:

  • .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 反序列化注意点》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jackletter

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

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

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

打赏作者

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

抵扣说明:

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

余额充值