【工作中问题解决实践 四】动态解析Json结构最佳实践(下)

简介: 【工作中问题解决实践 四】动态解析Json结构最佳实践(下)

转换路径

因为生成的路径多有Propertys和item,所以我将拿到的路径做处理,得到新的路径去Json数据里找值,生成路径代码如下所示:

#region 替换掉所有的properties
        public string GeValuePath(string oldPath)
        {
            var newPath = oldPath.Replace("properties.", "");  //处理所有properties
            var lastPath = newPath.Replace(".items", "[0]"); //这里是个大坑!!!!!
            return lastPath;
        }
        #endregion 替换掉所有的properties

没错,很快我就发现了问题,object类型还好,Array类型就麻烦了,由于JsonSchema只是描述Json结构的,所以它无需拥有每个数组的结构,也就没有每个数组的路径:看下JsonSchema长这样:

{
  "$id": "http://example.com/example.json",
  "type": "object",
  "properties": {
    "checked": {
      "$id": "/properties/checked",
      "type": "boolean",
      "title": "The Checked Schema ",
      "description": "Equal",
      "default": false,
      "examples": [
        false
      ]
    },
    "dimensions": {
      "$id": "/properties/dimensions",
      "type": "object",
      "properties": {
        "width": {
          "$id": "/properties/dimensions/properties/width",
          "type": "integer",
          "title": "The Width Schema ",
          "description": "Equal",
          "default": 0
        },
        "height": {
          "$id": "/properties/dimensions/properties/height",
          "type": "integer",
          "title": "The Height Schema ",
          "description": "Equal",
          "default": 0,
          "examples": [
            10
          ]
        }
      }
    },
    "variables": { 
      "$id": "/properties/variables",
      "type": "array",   //就是这里的问题,不管你有多少个元素,它只给你展示结构
      "items": { 
        "$id": "/properties/variables/items",
        "type": "object",
        "properties": {
          "code": {
            "$id": "/properties/variables/items/properties/code",
            "type": "string",
            "title": "The Code Schema ",
            "description": "Equal",
            "default": "",
            "examples": [
              "id"
            ]
          },
          "name": {
            "$id": "/properties/variables/items/properties/name",
            "type": "string",
            "title": "The Name Schema ",
            "description": "Equal",
            "default": "",
            "examples": [
              "业务实体数据Id"
            ]
          },
          "dataType": {
            "$id": "/properties/variables/items/properties/dataType",
            "type": "string",
            "title": "The Datatype Schema ",
            "default": "",
            "examples": [
              "String"
            ]
          },
          "defaultValue": {
            "$id": "/properties/variables/items/properties/defaultValue",
            "type": "string",
            "title": "The Defaultvalue Schema ",
            "description": "Equal",
            "default": "",
            "examples": [
              ""
            ]
          },
          "showFlag": {
            "$id": "/properties/variables/items/properties/showFlag",
            "type": "string",
            "title": "The Showflag Schema ",
            "description": "Equal",
            "default": "",
            "examples": [
              "0"
            ]
          },
          "showValue": {
            "$id": "/properties/variables/items/properties/showValue",
            "type": "string",
            "title": "The Showvalue Schema ",
            "description": "Equal",
            "default": "",
            "examples": [
              ""
            ]
          }
        }
      }
    },
    "id": {
      "$id": "/properties/id",
      "type": "integer",
      "title": "The Id Schema ",
      "description": "Mapping",
      "default": 0,
      "examples": [
        1
      ]
    },
    "name": {
      "$id": "/properties/name",
      "type": "string",
      "title": "The Name Schema ",
      "description": "Equal",
      "default": "",
      "examples": [
        "A green door"
      ]
    },
    "price": {
      "$id": "/properties/price",
      "type": "number",
      "title": "The Price Schema ",
      "description": "Equal",
      "default": 0,
      "examples": [
        12.5
      ]
    },
    "tags": {
      "$id": "/properties/tags",
      "type": "array",
      "items": {
        "$id": "/properties/tags/items",
        "type": "string",
        "title": "The 0th Schema ",
        "default": "",
        "examples": [
          "home",
          "green"
        ]
      }
    }
  }
}

由于结构使我拿不到其它数组元素的路径,我也就拿不到所有数组元素的节点的值,我想了很多,甚至递归判断共有多少个节点,和武哥讨论后,他给出了一个方案,就是拿大的装小的,现在json数据比schema大,那么可以先获取数据的节点路径和值,再将节点路径简化为schema的路径(也就是把各种索引去掉),这样就可以拿到规则。

最佳实践

采用大装小的战略后,事情解决起来很容易,事实证明,换个角度思考,可能问题就解决掉了。

初始化Json数据字典

初始化数据的<path,value>字典

#region 递归JsonValue树获取所有路径-值字典
        public void JsonValueTraverse(JToken json, ref Dictionary<string, string> jsonDic)
        {
            if (!json.HasValues)  //如果json没有子节点了,说明已经到了叶子节点,该完整路径为叶子节点path
            {
                var value = json.Value<object>().ToString();
                if (!jsonDic.ContainsKey(json.Path))  //如果已经存在了,则不需要重复添加
                {
                    jsonDic.Add(json.Path, value);
                }
                else {
                    logger.Error("添加了重复节点,节点路径为" + json.Path + "节点值为" + value);
                }
            }
            foreach (var item in json.Children())    
            {
                JsonValueTraverse(item, ref jsonDic);   //递归选取子节点
            }
        }
        #endregion 递归JsonValue树获取所有路径-值字典

转换为schema路径

将数据路径转换为Schema路径

#region 转换为schema路径
        public string GetRulePath(string oldPath)
        {
            var newPath = oldPath.Replace(".", ".properties.");  //处理所有properties
            var expr = @"\[\d+\]";   
            var lastPath = Regex.Replace(newPath, expr, ".items");   //用正则替换所有索引
            return lastPath;
        }
        #endregion 转换为schema路径

得到最终字典

代码清单:

#region 初始化路径-(值,规则)字典
        /// <summary>
        /// 初始化字典
        /// </summary>
        /// <param name="json"></param>
        /// <param name="schema"></param>
        /// <param name="type">0表示json数据,1表示xml数据</param>
        /// <returns></returns>
        public Dictionary<string, JsonSchemaObject> InitialJsonRule(string json, string schema, int type)
        {
            var jsonValue = JToken.Parse(json);
            var JsonSchema = JToken.Parse(schema);
            //初始化路径--规则字典
            Dictionary<string, string> jsonDic = new Dictionary<string, string>();
            JsonValueTraverse(jsonValue, ref jsonDic);
            Dictionary<string, JsonSchemaObject> ruleDic = new Dictionary<string, JsonSchemaObject>();
            //规范化字典名称
            foreach (var item in jsonDic)
            {
                JsonSchemaObject jso = new JsonSchemaObject();
                var schemaPath = GetRulePath(item.Key);  //将路径转为schemaPath去获取规则
                if (type == 1)
                {
                    schemaPath = GetStrAfterFirstPoint(schemaPath); //如果是xml类型的数据,还需要把路径头的名去掉
                }
                JToken node = JsonSchema.SelectToken(schemaPath);
                if (node != null)
                {
                    if (node.SelectToken("description") != null)
                    {
                        jso.rule = node.Value<string>("description");//从Json里取出规则值
                    }
                    else {
                        jso.rule = "Equal";
                    }
                    jso.value = item.Value;
                    ruleDic.Add(item.Key, jso);  //只存储有规则的字段,没有规则的不管,不比较,也不关心
                }
            }
            return ruleDic;
        }
        #endregion 初始化路径-(值,规则)字典

因为xml数据转为json前,需要带着最外层尖括号的名字,为了路径一致,这里我们去掉

#region xml转json需要替换头一个名
        public string GetStrAfterFirstPoint(string schema)
        {
            var index = schema.IndexOf(".");
            var newSchema = schema.Substring(index);
            return newSchema;
        }
        #endregion xml转json需要替换头一个名

附送一个xml转json的方法哦:

#region xml转为json
        public string XmlToJson(string xmlStr)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlStr);
            return Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc);
        }
        #endregion xml转为json

思考过程

一开始想着遍历JsonSchema,拿到【schema路径,规则】字典,然后再通过schem路径遍历json数据获取路径的值,结果遇到数组的情况就不能取到正确的值了,这就是小装不下大

发现实现不了后通过遍历数据Json,拿到【数据路径,数据值】字典,然后将数据路径转为schema路径去拿规则,这个就是大可以缩小

第一步将Schema和Json数据都存储好之后,使用上述方法读取,要知道读取之后只是简单的字符串,在尝试了反序列化字典无果之后,突发奇想,如果把Json当成颗多叉树呢?,使用递归遍历的方式不就可以拿到所有节点了么?

做完之后有些反思:解决方案性学习和原理性学习是两回事儿,譬如CLR这类的可以追更溯源,而解决方案类问题不应将过多精力投入去从基础学习,应该自顶向下,先找到大致的解决方案,然后哪里不会再查哪里,这样效率高。就像Schema这个学习,之前学习虽说出了几篇博文,但对于实质问题的解决并没有帮助,反倒是直接搜索解决方案,之后对Schema的理解更深了。对JToken 的使用也加深了。

相关文章
|
6月前
|
JSON 缓存 自然语言处理
多语言实时数据微店商品详情API:技术实现与JSON数据解析指南
通过以上技术实现与解析指南,开发者可高效构建支持多语言的实时商品详情系统,满足全球化电商场景需求。
|
8月前
|
存储 JSON 关系型数据库
【干货满满】解密 API 数据解析:从 JSON 到数据库存储的完整流程
本文详解电商API开发中JSON数据解析与数据库存储的全流程,涵盖数据提取、清洗、转换及优化策略,结合Python实战代码与主流数据库方案,助开发者构建高效、可靠的数据处理管道。
|
7月前
|
JSON 算法 API
淘宝商品评论API接口核心解析,json数据返回
淘宝商品评论API是淘宝开放平台提供的数据服务接口,允许开发者通过编程方式获取指定商品的用户评价数据,包括文字、图片、视频评论及评分等。其核心价值在于:
|
5月前
|
JSON Java Go
【GoGin】(2)数据解析和绑定:结构体分析,包括JSON解析、form解析、URL解析,区分绑定的Bind方法
bind或bindXXX函数(后文中我们统一都叫bind函数)的作用就是将,以方便后续业务逻辑的处理。
401 3
|
5月前
|
XML JSON 数据处理
超越JSON:Python结构化数据处理模块全解析
本文深入解析Python中12个核心数据处理模块,涵盖csv、pandas、pickle、shelve、struct、configparser、xml、numpy、array、sqlite3和msgpack,覆盖表格处理、序列化、配置管理、科学计算等六大场景,结合真实案例与决策树,助你高效应对各类数据挑战。(238字)
644 0
|
9月前
|
JSON 定位技术 PHP
PHP技巧:解析JSON及提取数据
这就是在PHP世界里探索JSON数据的艺术。这场狩猎不仅仅是为了获得数据,而是一种透彻理解数据结构的行动,让数据在你的编码海洋中畅游。通过这次冒险,你已经掌握了打开数据宝箱的钥匙。紧握它,让你在编程世界中随心所欲地航行。
276 67
|
6月前
|
JSON 自然语言处理 API
多语言实时数据淘宝商品评论API:技术实现与JSON数据解析指南
淘宝商品评论多语言实时采集需结合官方API与后处理技术实现。建议优先通过地域站点适配获取本地化评论,辅以机器翻译完成多语言转换。在合规前提下,企业可构建多语言评论数据库,支撑全球化市场分析与产品优化。
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1164 29
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
490 4
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

推荐镜像

更多
  • DNS