[STJson]在.NET中使用JsonPath

这篇具有很好参考价值的文章主要介绍了[STJson]在.NET中使用JsonPath。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JsonPath简介

JsonPath是源自于XPath的使用方式,总所周知XPathXML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。显而易见JsonPath是用于Json的。

.NET中有不少第三方库提供了JsonPath的功能,如很流行的Newtonsoft.json,它目前应该是在.NET中最流行的Json库,但似乎它的JsonPath功能有一些简陋。为了确认这一点(而不是博主不会用),博主特意去翻阅了它的源代码,确实仅有一些基本的功能,且兼容性不是很好。

STJson

STJson是博主自己开发的一套库,包含了Json的解析,序列化和反序列化甚至数据聚合等功能,同时也包含了JsonPath功能。应该是JsonPath支持算是相对比较完整的了。因为博主并非像其他库一样将JsonPath字符串进行一个正则解析拆分然后判断。博主为其写了一个语法解析器,所以在STJsonJsonPath可以使用很复杂的表达式,且提供了用户自定义函数和调试功能。

项目地址: https://github.com/DebugST/STJson
在线教程: https://debugst.github.io/STJson/tutorial_cn.html
Nuget: https://www.nuget.org/packages/STLib.Json

测试数据

[{
    "name": "Tom", "age": 16, "gender": 0,
    "hobby": [
        "cooking", "sing"
    ]
},{
    "name": "Tony", "age": 16, "gender": 0,
    "hobby": [
        "game", "dance"
    ]
},{
    "name": "Andy", "age": 20, "gender": 1,
    "hobby": [
        "draw", "sing"
    ]
},{
    "name": "Kun", "age": 26, "gender": 1,
    "hobby": [
        "sing", "dance", "rap", "basketball"
    ]
}]

假设上述数据保存在test.json文件中。将其加载到程序中。

var json_src = STJson.Deserialize(System.IO.File.ReadAllText("./test.json"));

选择器

STJsonPath支持一下选择器。

选择器 说明
$ 根节点选择器,可视作代表根节点对象。
@ 当前元素选择器,在遍历过程中指代当前被遍历的元素。
* 通配符,表示可以代表任何一个节点。
. 子节点选择器,指定子节点的key。
深度选择器,表示可以是任意路径。
[‘<name>’(,‘<name>’)] 列表选择器,指定子节点的key集合。
[<number>(,(<number>))] 列表选择器,指定子节点的index集合。
[Start:End:Step] 切片选择器,用于指定索引区间。
[(<expression>)] 表达式选择器,用于输入一个运算表达式,并将结果作为索引继续向下选择。
[?(<expression>)] 表达式选择器,用于输入一个运算表达式,并将结果转换为布尔值,决定是否继续选择。

注: 在STJsonPath$开头并非必修的,且在内部会移除掉开头的$@。他们仅用于在表达式中作为变量使用。应为博主认为,作为开头似乎有点多余。

构建JsonPath

通过以下方式可以构建一个STJsonPath

// var jp = new STJsonPath("$[0]name");
// var jp = new STJsonPath("$[0].name");
var jp = new STJsonPath("[0]'name'"); // 以上方式均可以使用 $不是必须的
Console.WriteLine(jp.Select(json_src));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
["Tom"]

当然在STJson中的扩展函数中已经集成STJsonPath,可以通过下面的方式直接使用:

// var jp = new STJsonPath("[0].name");
// Console.WriteLine(json_src.Select(jp));
Console.WriteLine(json_src.Select("[0].name")); // 内部动态构建 STJsonPath
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
["Tom"]

STJsonPath中允许使用'或者",比如:'a.b' "a.b"STJsonPath会将其视为一个独立的个体。而不是两个。列如有如下Json

{
    "a.b": "this is a test"
}

很明显通过Select("a.b")是无法获取到数据的,需要通过Select("'a.b'")

string strTemp = "{\"a.b\": \"this is a test\"}";
var json_temp = STJson.Deserialize(strTemp);
Console.WriteLine(json_temp.Select("a.b"));
Console.WriteLine(json_temp.Select("'a.b'"));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[]
["this is a test"]

在字符串中支持\进行转义:
\r \n \t \f \b \a \v \0 \x.. \u... \.

通配符

通配符可表示当前层级中的任何一个节点。获取所有人员姓名。

Console.WriteLine(json_src.Select("*.name").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    "Tom", "Tony", "Andy", "Kun"
]

深度选择器

深度选择器与通配符类似,但深度选择器可以是任意层级。

Console.WriteLine(json_src.Select("..name").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    "Tom", "Tony", "Andy", "Kun"
]

列表选择器

在上面的表格中可以看到有两个列表选择器,但事实上可以混用,也就是说[0,'abc',1]这样也是可以被允许的。在内部会直接创建两个列表选择器,而根据情况选择使用哪一个。
选择索引为02的元素。

Console.WriteLine(json_src.Select("[0,2]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    {
        "name": "Tom",
        "age": 16,
        "gender": 0,
        "hobby": [
            "cooking", "sing"
        ]
    }, {
        "name": "Andy",
        "age": 20,
        "gender": 1,
        "hobby": [
            "draw", "sing"
        ]
    }
]

对于int索引可以使用负数,比如-1则表示获取最后一个元素。当STJsonPath检测到负数时候会执行STJson.Count - n将结果作为索引。

//Console.WriteLine(json_src.Select("-1").ToString(4));
Console.WriteLine(json_src.Select("[-1]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    {
        "name": "Kun",
        "age": 26,
        "gender": 1,
        "hobby": [
            "sing", "dance", "rap", "basketball"
        ]
    }
]

切片选择器

切片选择器用于在数组中选择一个片段,切片选择器默认值[0:-1:1],切片中的三个值等同于for循环中的三个条件,所以原理与效果就不再说明。

expression range note
[::] 0 <= R <= {OBJ}.length - 1 等同于*
[5:] 5 <= R <= {OBJ}.length - 1 从第6个元素开始,获取所有元素
[-1:0] {OBJ}.length - 1 >= R >= 0 倒序获取数据
[0::2] 0 <= R <= {OBJ}.length - 1 顺序获取数据,且间隔一个数据

切片选择器中至少出现一个:step大于0,否则将获得异常。

Console.WriteLine(json_src.Select("[-1:]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    {
        "name": "Kun",
        "age": 26,
        "gender": 1,
        "hobby": [
            "sing", "dance", "rap", "basketball"
        ]
    }
]

表达式

[?()]中可支持下列运算符,优先级从上至下依次升高

  • && ||
  • < <= > >= == != re
  • & | << >> ^ ~
  • + -
  • * / %
  • in nin anyof
  • !
operator note e.g
re 正则表达式 [?(@.name re ‘un’)]
in 左边的值或数组包含在右边的数组中 [?(@.age in [16,20])]
nin 左边的值或数组不包含在右边的数组中 [?(@.hobby nin [‘sing’,‘draw’])]
anyof 左边的值或数组和右边的数组存在交集 [?(@.hobby anyof [‘sing’,‘draw’])]

表达式有两种模式:

  • [?(<expression>)] - 过滤表达式,用于计算出一个布尔值,确定是否继续匹配。
  • [(<expression>)] - 普通表达式,用于计算出一个值,并将值作为索引继续匹配。

过滤表达式

选中name中包含字母ku的元素:

//Console.WriteLine(json_src.Select("*.[?(@.name == 'kun')]").ToString(4));
Console.WriteLine(json_src.Select("*.[?(@.name re '(?i)ku')]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    {
        "name": "Kun",
        "age": 26,
        "gender": 1,
        "hobby": [
            "sing", "dance", "rap", "basketball"
        ]
    }
]

(?i)中的i表示忽略大小写,其正则表达式以.NetRegex为标准。(?...)开头则表示设置匹配模式。至于匹配模式自行查阅相关资料。

选中hobby不包含singswing的元素:

Console.WriteLine(json_src.Select("*.[?(@.hobby nin ['sing','draw'])]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    {
        "name": "Tony",
        "age": 16,
        "gender": 0,
        "hobby": [
            "game", "dance"
        ]
    }
]

普通表达式

普通表达式会将结果作为STJsonPath的部分继续匹配。

Console.WriteLine(json_src.Select("*.[('na' + 'me')]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    "Tom", "Tony", "Andy", "Kun"
]

[('na' + 'me')]'na' + 'me'的结果为'name',并且会将这个值作为索引,所以上述效果等同于*.name,当然返回值也可以是一个集合。

Console.WriteLine(json_src.Select("*.[(['na' + 'me', 'age', 0, 1 + 1])]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    "Tom", 16, "Tony", 16, "Andy", 20, "Kun", 26
]

上面表达式的结算结果值为['name', 'age', 0, 2]。但是很显然02将不会起到任何作用,因为第二层的数据对象并不是一个数组。

上面的表达式等同于*.['name', 'age', 0, 2]。如果将上面的换成第三层会得到下面的结果。

Console.WriteLine(json_src.Select("*.*.[(['na' + 'me', 'age', 0, 1 + 1])]").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
[
    "cooking", "game", "draw", "sing", "rap"
]

可以看到'name''age'对于hobby来说是无效的,因为hobby是一个数组。

测试表达式

可能读者并不了解表达式在内部是如何被执行了并且会输出什么样的结果,博主提供了一个静态测试函数TestExpression()可用于调试表达式。若有什么不明白的地方测试一下就会看到过程及结果。

Console.WriteLine(STJsonPath.TestExpression(
    null,           // [STJson] 用于替代表达式中出现的 $
    null,           // [STJson] 用于替代表达式中出现的 @
    "1+2+3"         // 表达式文本
    ).ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
{
    "type": "expression",
    "parsed": "{1 + 2 + 3}",        // 格式化后的文本 {}表示此部分需要单独执行 如: [1, {1+1}, 3]
    "polish": [
        "1", "2", " + ", "3", " + " // 逆波兰方式排列
    ],
    "steps": [                      // 执行步骤
        {
            "type": "excute",
            "operator": "+",
            "get_left_token": {     // 计算操作符左边元素的值,表达式左边也可能是一个表达式
                "parsed": "1",
                "type": "value",
                "result": {
                    "value_type": "Long",
                    "text": "1"
                }
            },
            "get_right_token": {
                "parsed": "2",
                "type": "value",
                "result": {
                    "value_type": "Long",
                    "text": "2"
                }
            },
            "result": {             // 该步骤执行结果
                "value_type": "Long",
                "text": "3"
            }
        }, {
            "type": "excute",
            "operator": "+",
            "get_left_token": {     // 此时操作符左边的元素为上一步的计算结果
                "parsed": "3",
                "type": "value",
                "result": {
                    "value_type": "Long",
                    "text": "3"
                }
            },
            "get_right_token": {
                "parsed": "3",
                "type": "value",
                "result": {
                    "value_type": "Long",
                    "text": "3"
                }
            },
            "result": {
                "value_type": "Long",
                "text": "6"
            }
        }
    ],
    "check_result": {               // 清空波兰表达式数据栈,确定最终输出结果。
        "parsed": "6",
        "type": "value",
        "result": {
            "value_type": "Long",
            "text": "6"
        }
    },
    "return": {                     // 最终返回值
        "value_type": "Long",
        "text": "6",
        "bool": true                // 如果用作布尔表达式则转换为 true
    }
}

如果过程不重要,仅仅是想看执行结果。

Console.WriteLine(STJsonPath.TestExpression(
    null,           // [STJson] 用于替代表达式中出现的 $
    null,           // [STJson] 用于替代表达式中出现的 @
    "1+2+3"         // 表达式文本
    ).SelectFirst("return").ToString(4));
/*******************************************************************************
 *                                [output]                                     *
 *******************************************************************************/
{
    "return": {                     // 最终返回值
        "value_type": "Long",
        "text": "6",
        "bool": true                // 如果用作布尔表达式则转换为 true
    }
}

结束

上面仅仅列举了部分常用功能,在STJson中还有许多其他功能由于篇幅原因这里仅介绍这么多,读者可以查看在线完整教程。
https://debugst.github.io/STJson/tutorial_cn.html
如果你觉得项目不错可以支持一下博主:
https://github.com/DebugST/STJson文章来源地址https://www.toymoban.com/news/detail-551377.html

到了这里,关于[STJson]在.NET中使用JsonPath的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Postman 脚本中使用jsonpath提取数据

    jsonpath 在处理 json 格式的数据方面是无敌的存在,前边我也篇关于 jsonpath 介绍的文章 Json 数据提取神器 jsonpath ,今天介绍 jsonpath 在 Postman 脚本中的应用 Postman 的脚本是 JavaScript 语言,因此需要准备JS版本的JSONPath JSONPath Github官网 说明: Github官网提供的JS语言的 JSONPath 版本

    2024年02月10日
    浏览(44)
  • Python中jsonpath库使用,及与xpath语法区别

    jsonpath库使用 pip install jsonpath 基本语法 JSONPath语法元素和对应XPath元素的对比

    2024年02月12日
    浏览(43)
  • 【Python从入门到进阶】30、JSONPath的介绍和使用

    接上篇《29、xpath抓取站长素材图片》 上一篇我们讲解了如何利用xpath来抓取站长素材网站的图片区首页的所有图片,本篇我们来介绍JSONPath的基础和具体使用。 1、什么是JSONPath? JSONPath是一种用于在JSON(JavaScript Object Notation)数据中定位和提取特定元素的查询语言。它类似于

    2024年01月22日
    浏览(42)
  • 【Python爬虫开发实战②】使用urllib以及jsonpath爬取即将上映电影信息

    🚀 个人主页 :为梦而生~ 关注我一起学习吧! 💡 专栏 :python网络爬虫从基础到实战 欢迎订阅!后面的内容会越来越有意思~ 💡 往期推荐 : ⭐️首先,我们前面讲了多篇基础内容: 【Python爬虫开发基础④】爬虫原理 【Python爬虫开发基础⑤】HTML概述与基本标签详解 【P

    2024年02月12日
    浏览(48)
  • JsonPath

    JsonPath是一种用于处理JSON数据的查询语言,它允许你通过路径表达式在JSON文档中查找和访问节点。JsonPath的语法相对简单,采用了开发语言友好的表达式形式。它将JSON数据转换为DOM树状结构,并提供在数据结构树中寻找节点的能力。 JsonPath的路径表达式由节点名组成,节点之

    2024年02月01日
    浏览(29)
  • python中jsonpath的用法

        接口返回的json数据,需要取值后断言,一般我们是使用jsonpath来提取接口返回的数据 JsonPath模块,是一个专门用于处理Json字符串的模块。JsonPath相当于是Xpath 部署JsonPath 通过pip install jsonpath来进行安装 通过JsonPath获得的内容,会以list的形式进行返回,也就意味着你的jso

    2024年02月13日
    浏览(36)
  • Python爬虫——解析_jsonpath

    jsonpath的安装 jsonpath的使用: json文件: 书店所有书的作者 所有的作者 store下面所有的元素 store里面所有东西的price 第三本书 最后一本书 前两本书 条件过滤需要在()的前面添加一个? 过滤出所有包含isbn的书 哪本书超过了10块钱 参考:https://blog.csdn.net/Obstinate_L/article/details/1

    2024年02月14日
    浏览(43)
  • 爬虫 — JsonPath 和 CSV 文件读写

    JsonPath 是一种简单的方法来 提取给定 JSON 文档 的部分内容,JsonPath 有许多编程语言,如 Javascript,Python,PHP 和 JAVA。 JsonPath 提供的 JSON 解析非常强大,它提供了 类似正则表达式的语法 ,基本上可以满足所有你想要获得的 JSON 内容。但 JsonPath 解析的数据 只针对 JSON 格式的数

    2024年02月07日
    浏览(36)
  • 接口测试 04 -- Jsonpath断言、接口关联处理

    JsonPath是一种用于在JSON数据中定位和提取特定数据的表达式语言。它类似于XPath用于XML的定位和提取,可以帮助我们灵活地从复杂的JSON结构中获取所需的数据。 ● JsonPath可处理的报文类型为字典类型 ● 通过JsonPath成功获得的内容,会以list的形式进行返回,也就意味着你的

    2024年01月24日
    浏览(53)
  • Python爬虫学习笔记(五)————JsonPath解析

    目录 1.JSONPath —— xpath在json的应用 2.JSONPath 表达式 3.jsonpath的安装及使用方式 4.jsonpath的使用 5.JSONPath语法元素和对应XPath元素的对比 6.实例  (1)商店案例 (2) 解析淘票票的“城市选择”数据 1. JSONPath —— xpath在json的应用 xml最大的优点就有大量的工具可以分析,转换,

    2024年02月17日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包