关于Json数据动态解析的处理方法
Posted SHao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Json数据动态解析的处理方法相关的知识,希望对你有一定的参考价值。
有时会遇到json数据是动态的,没有固定的格式和字段,没办法反序列化固定model进行解析,只能用dynamic来接收。如何解析呢?想到的办法是转化成键值对,用Dictionary<string, object> 数据结构来储存,后续获取匹配等处理效率也很高。
首先用到Newtonsoft.Json来解析,简单介绍下目前用到的这里面的几个类的作用:
- JToken:抽象类,所有json元素描述的父类
- JObject:json对象描述,对应
- JProperty:json中key:value的描述,对应中的键值
- JArray :描述json数组,对应[]
- 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数据动态解析的处理方法的主要内容,如果未能解决你的问题,请参考以下文章