关于Json数据动态解析的处理方法

  有时会遇到json数据是动态的,没有固定的格式和字段,没办法反序列化固定model进行解析,只能用dynamic来接收。如何解析呢?想到的办法是转化成键值对,用Dictionary<string, object> 数据结构来储存,后续获取匹配等处理效率也很高。

  首先用到Newtonsoft.Json来解析,简单介绍下目前用到的这里面的几个类的作用:

  1. JToken:抽象类,所有json元素描述的父类
  2. JObject:json对象描述,对应{}
  3. JProperty:json中key:value的描述,对应{}中的键值
  4. JArray :描述json数组,对应[]
  5. JValue:描述json中的value

  写了个解析json为字典的扩展方法,支持设置解析的深度,一开始没有发现JToken有Path这个属性,自己写了全路径的拼接(代码第一个方法),正好可以加深对json和Newtonsoft.Json的理解和应用,代码如下: 

 1 using Newtonsoft.Json.Linq;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace Extensions
 8 {
 9     public static class JsonHelperExtension
10     {
11         /// <summary>
12         /// json数据解析字典数据
13         /// </summary>
14         /// <param name="keyHeadName">键头</param>
15         /// <param name="key"></param>
16         /// <param name="targetJToken">json源数据</param>
17         /// <param name="arrayStartIndex">数组索引</param>
18         /// <param name="dic">字典</param>
19         /// <param name="depth">深度</param>
20         /// <returns></returns>
21         public static Dictionary<string, object> GetDictionary(Dictionary<string, object> dic,string keyHeadName, JToken targetJToken , string key=null,
22             int arrayStartIndex=0, int depth = -2)
23         {
24             if (depth + 1 == 0) return dic;
25             foreach (var token in targetJToken)
26             {
27                 if (targetJToken.Type.Equals(JTokenType.Array))//json数组
28                 {
29                     var jArray = targetJToken.ToObject<JArray>();
30                     var pathKey = key + arrayStartIndex++;
31                     if (token.Type.Equals(JTokenType.String) || token.Type.Equals(JTokenType.Integer) ||
32                         token.Type.Equals(JTokenType.Float))//JValue
33                     {
34                         var jValue = token.ToObject<JValue>();
35                         var val = jValue?.Value;
36                         dic.Add(keyHeadName + ":" + pathKey, val);
37                         continue;
38                     }
39                     else//非JValue
40                     {
41                         GetDictionary(dic, keyHeadName, token,  pathKey, 0, depth - 1);
42                     }
43                 }
44                 else//非json数组
45                 {
46                     var jProperty = token.ToObject<JProperty>();
47                     var pathKey = key == null ? jProperty?.Name : key + "." + jProperty?.Name;
48                     if (jProperty.Value.Type.Equals(JTokenType.String) || jProperty.Value.Type.Equals(JTokenType.Integer) ||
49                         jProperty.Value.Type.Equals(JTokenType.Float))//JValue
50                     {
51                         var jValue = jProperty.Value.ToObject<JValue>();
52                         var val = jValue?.Value;
53                         dic.Add(keyHeadName + ":" + pathKey, val);
54                         continue;
55                     }
56                     else//非JValue
57                     {
58                         GetDictionary(dic, keyHeadName, jProperty.Value, pathKey, 0, depth - 1);
59                     }
60                 }
61             }
62 
63             return dic;
64         }
65 
66         /// <summary>
67         /// json数据解析字典数据
68         /// </summary>
69         /// <param name="keyHeadName">键头</param>
70         /// <param name="currentJToken">目标json对象</param>
71         /// <param name="dic">字典</param>
72         /// <param name="depth">小于-1全遍历</param>
73         /// <returns></returns>
74         public static Dictionary<string, object> GetDictionary(string keyHeadName, JToken currentJToken,
75             Dictionary<string, object> dic, int depth = -2)
76         {
77             var key = keyHeadName;
78             if (depth + 1 == 0) return dic;
79             foreach (var jsonValue in currentJToken)
80             {
81                 if (jsonValue.Type.Equals(JTokenType.String) || jsonValue.Type.Equals(JTokenType.Integer) ||
82                     jsonValue.Type.Equals(JTokenType.Float))
83                 {
84                     var jValue = jsonValue.ToObject<JValue>();
85                     key = keyHeadName + ":" + jsonValue.Path.Replace("[", "")
86                         .Replace("]", "");
87                     dic.Add(key, jValue?.Value);
88                     continue;
89                 }
90                 else
91                 {
92                     dic = GetDictionary(key, jsonValue, dic, depth - 1);
93                 }
94             }
95 
96             return dic;
97         }
98     }
99 }
View Code

  测试一下:

 1         static void Main(string[] args)
 2         {
 3             var json =
 4                 "{\"key\":\"value1\",\"keyX\":{\"key\":\"value2\",\"keyX\":[{\"key\":\"value3\"},{\"key\":\"value4\"}],\"keyXX\":[\"value5\",\"value6\"]},\"keyXX\":[[{\"key\":\"value7\"},{\"key\":\"value8\"}],[\"value9\",\"value10\"]]}";
 5             var jToken = JToken.Parse(json);
 6 
 7             var dic1 = new Dictionary<string, object>();
 8             var dic2 = new Dictionary<string, object>();
 9             dic1 = JsonHelperExtension.GetDictionary(dic1, "S", jToken, null, 0);
10             dic2 = JsonHelperExtension.GetDictionary("S", jToken, dic2, -2);
11 
12             Console.WriteLine(JsonConvert.SerializeObject(dic1));
13             Console.WriteLine(JsonConvert.SerializeObject(dic2));
14 
15             Console.ReadKey();
16         }        
View Code

  解析结果正确,两个方法结果一致:

 

posted @ 2022-01-25 23:07  JN-SHao  阅读(706)  评论(0编辑  收藏  举报