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

Posted SHao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于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的理解和应用,代码如下: 

 using Newtonsoft.Json.Linq;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 
 namespace Extensions
 
     public static class JsonHelperExtension
     
         /// <summary>
         /// json数据解析字典数据
         /// </summary>
         /// <param name="keyHeadName">键头</param>
         /// <param name="key"></param>
         /// <param name="targetJToken">json源数据</param>
         /// <param name="arrayStartIndex">数组索引</param>
         /// <param name="dic">字典</param>
         /// <param name="depth">深度</param>
         /// <returns></returns>
         public static Dictionary<string, object> GetDictionary(Dictionary<string, object> dic,string keyHeadName, JToken targetJToken , string key=null,
             int arrayStartIndex=0, int depth = -2)
         
             if (depth + 1 == 0) return dic;
             foreach (var token in targetJToken)
             
                 if (targetJToken.Type.Equals(JTokenType.Array))//json数组
                 
                     var jArray = targetJToken.ToObject<JArray>();
                     var pathKey = key + arrayStartIndex++;
                     if (token.Type.Equals(JTokenType.String) || token.Type.Equals(JTokenType.Integer) ||
                         token.Type.Equals(JTokenType.Float))//JValue
                     
                         var jValue = token.ToObject<JValue>();
                         var val = jValue?.Value;
                         dic.Add(keyHeadName + ":" + pathKey, val);
                         continue;
                     
                     else//非JValue
                     
                         GetDictionary(dic, keyHeadName, token,  pathKey, 0, depth - 1);
                     
                 
                 else//非json数组
                 
                     var jProperty = token.ToObject<JProperty>();
                     var pathKey = key == null ? jProperty?.Name : key + "." + jProperty?.Name;
                     if (jProperty.Value.Type.Equals(JTokenType.String) || jProperty.Value.Type.Equals(JTokenType.Integer) ||
                         jProperty.Value.Type.Equals(JTokenType.Float))//JValue
                     
                         var jValue = jProperty.Value.ToObject<JValue>();
                         var val = jValue?.Value;
                         dic.Add(keyHeadName + ":" + pathKey, val);
                         continue;
                     
                     else//非JValue
                     
                         GetDictionary(dic, keyHeadName, jProperty.Value, pathKey, 0, depth - 1);
                     
                 
             
 
             return dic;
         
 
         /// <summary>
         /// json数据解析字典数据
         /// </summary>
         /// <param name="keyHeadName">键头</param>
         /// <param name="currentJToken">目标json对象</param>
         /// <param name="dic">字典</param>
         /// <param name="depth">小于-1全遍历</param>
         /// <returns></returns>
         public static Dictionary<string, object> GetDictionary(string keyHeadName, JToken currentJToken,
             Dictionary<string, object> dic, int depth = -2)
         
             var key = keyHeadName;
             if (depth + 1 == 0) return dic;
             foreach (var jsonValue in currentJToken)
             
                 if (jsonValue.Type.Equals(JTokenType.String) || jsonValue.Type.Equals(JTokenType.Integer) ||
                     jsonValue.Type.Equals(JTokenType.Float))
                 
                     var jValue = jsonValue.ToObject<JValue>();
                     key = keyHeadName + ":" + jsonValue.Path.Replace("[", "")
                         .Replace("]", "");
                     dic.Add(key, jValue?.Value);
                     continue;
                 
                 else
                 
                     dic = GetDictionary(key, jsonValue, dic, depth - 1);
                 
             
 
             return dic;
         
     
 

  测试一下:

         static void Main(string[] args)
         
             var json =
                 "\\"key\\":\\"value1\\",\\"keyX\\":\\"key\\":\\"value2\\",\\"keyX\\":[\\"key\\":\\"value3\\",\\"key\\":\\"value4\\"],\\"keyXX\\":[\\"value5\\",\\"value6\\"],\\"keyXX\\":[[\\"key\\":\\"value7\\",\\"key\\":\\"value8\\"],[\\"value9\\",\\"value10\\"]]";
             var jToken = JToken.Parse(json);
 
             var dic1 = new Dictionary<string, object>();
             var dic2 = new Dictionary<string, object>();
             dic1 = JsonHelperExtension.GetDictionary(dic1, "S", jToken, null, 0);
             dic2 = JsonHelperExtension.GetDictionary("S", jToken, dic2, -2);
 
             Console.WriteLine(JsonConvert.SerializeObject(dic1));
             Console.WriteLine(JsonConvert.SerializeObject(dic2));
 
             Console.ReadKey();
                 

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

 

以上是关于关于Json数据动态解析的处理方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 JSON 对象解析和处理大文件的更有效方法

关于易语言的json数据处理

MariaDB 动态列(Dynamic Columns)支持JSON格式存储数据

关于使用jq 处理json格式的简单笔记

关于PHP处理Json数据的例子

关于Node.js中HTTP请求返回数据需要JSON解析的问题