使用 System.Text.Json 获取嵌套属性

2023-12-22

我正在与System.Text.Json在我的项目中,因为我正在处理大文件,所以也决定使用它来处理 GraphQL 响应。

由于 GraphQL 的性质,有时我会得到高度嵌套的响应,这些响应不固定,并且映射到类没有意义。我通常需要检查响应的一些属性。

我的问题是JsonElement。检查嵌套属性感觉非常笨拙,我觉得应该有更好的方法来解决这个问题。

例如,采用下面的代码来模拟我得到的响应。我只想检查是否存在 2 个属性(id 和originalSrc)以及它们是否确实获得了它们的值,但感觉就像我已经吃了一顿代码。有没有更好/更清晰/更简洁的方式来写这个?

var raw = @"{
""data"": {
""products"": {
    ""edges"": [
        {
            ""node"": {
                ""id"": ""gid://shopify/Product/4534543543316"",
                ""featuredImage"": {
                    ""originalSrc"": ""https://cdn.shopify.com/s/files/1/0286/pic.jpg"",
                    ""id"": ""gid://shopify/ProductImage/146345345339732""
                }
            }
        }
    ]
}
}
}";

var doc = JsonSerializer.Deserialize<JsonElement>(raw);

JsonElement node = new JsonElement();

string productIdString = null;

if (doc.TryGetProperty("data", out var data))
    if (data.TryGetProperty("products", out var products))
        if (products.TryGetProperty("edges", out var edges))
            if (edges.EnumerateArray().FirstOrDefault().ValueKind != JsonValueKind.Undefined && edges.EnumerateArray().First().TryGetProperty("node", out node))
                if (node.TryGetProperty("id", out var productId))
                    productIdString = productId.GetString();

string originalSrcString = null;

if(node.ValueKind != JsonValueKind.Undefined && node.TryGetProperty("featuredImage", out var featuredImage))
    if (featuredImage.TryGetProperty("originalSrc", out var originalSrc))
        originalSrcString = originalSrc.GetString();

if (!string.IsNullOrEmpty(productIdString))
{
    //do stuff
}

if (!string.IsNullOrEmpty(originalSrcString))
{
    //do stuff
}

这并不是大量的代码,但检查一些属性非常常见,我想要一种更清晰、更易读的方法。


您可以添加几个访问子项的扩展方法JsonElementvalue 按属性名称或数组索引,如果未找到则返回可为 null 的值:

public static partial class JsonExtensions
{
    public static JsonElement? Get(this JsonElement element, string name) => 
        element.ValueKind != JsonValueKind.Null && element.ValueKind != JsonValueKind.Undefined && element.TryGetProperty(name, out var value) 
            ? value : (JsonElement?)null;
    
    public static JsonElement? Get(this JsonElement element, int index)
    {
        if (element.ValueKind == JsonValueKind.Null || element.ValueKind == JsonValueKind.Undefined)
            return null;
        // Throw if index < 0
        return index < element.GetArrayLength() ? element[index] : null;
    }
}

现在,可以使用 null 条件运算符将访问嵌套值的调用链接在一起?. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-:

var doc = JsonSerializer.Deserialize<JsonElement>(raw);

var node = doc.Get("data")?.Get("products")?.Get("edges")?.Get(0)?.Get("node");

var productIdString = node?.Get("id")?.GetString();
var originalSrcString = node?.Get("featuredImage")?.Get("originalSrc")?.GetString();
Int64? someIntegerValue = node?.Get("Size")?.GetInt64();  // You could use "var" here also, I used Int64? to make the inferred type explicit.

Notes:

  • 如果传入元素不是预期类型(对象或数组或 null/缺失),上面的扩展方法将引发异常。你可以放松对ValueKind https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonelement.valuekind?view=netcore-3.1#System_Text_Json_JsonElement_ValueKind如果您不想在意外值类型上出现异常。

  • 有开放 API 增强请求将 JsonPath 支持添加到 JsonDocument/JsonElement #31068 https://github.com/dotnet/runtime/issues/31068。查询通过JSONPath https://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm如果实施的话,将使此类事情变得更容易。

  • 如果您从 Newtonsoft 移植代码,请注意JObject回报null对于丢失的财产,同时JArray抛出索引越界。因此您可能想使用JElement https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonelement.item?view=net-5.0#System_Text_Json_JsonElement_Item_System_Int32_当尝试模拟 Newtonsoft 的行为时,直接使用数组索引器,如下所示,因为它也会引发索引越界:

    var node = doc.Get("data")?.Get("products")?.Get("edges")?[0].Get("node");
    

演示小提琴here https://dotnetfiddle.net/3QVH6C.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 System.Text.Json 获取嵌套属性 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • 将所有依赖项从 .Net Standard 库复制到 .Net Framework 控制台应用程序

    在 net Framework 4 6 控制台应用程序中使用 net 标准项目后 net 标准项目的依赖项不会复制到输出目录中 这会导致缺少 dll 的运行时错误 对于引用的项目 复制本地 属性已经成立 一种可能的解决方案是在控制台应用程序
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile

随机推荐

  • 终止 EC2 实例时删除 EBS 卷,通过 terraform

    我的 tf 文件中有以下内容 provider aws region var aws region resource aws ebs volume agent xvdf count var ec2 count availability zo
  • HBase客户端-服务器版本兼容性

    我想知道如何知道我的 HBase 客户端的 jar 是否适合我的 HBase 服务器的版本 是否有任何地方指定 HBase 客户端 jar 支持哪些 HBase 版本 就我而言 我想将最新的 HBase 客户端 jar 2 4 5 与相当旧
  • 如何以 jQuery 方式搜索和操作复杂的 JavaScript 对象

    在 Web 应用程序的上下文中 我有一个服务器 它根据客户端的输入发送或接收 JSON 字符串 在客户端使用时 这些 JSON 字符串会立即转换为 JavaScript 对象 并以对象的形式存在 这些对象不是数组 而是数组 它们代表复杂的
  • 如何向 BLE 设备发送命令并显示结果

    Override public void onServicesDiscovered final BluetoothGatt gatt int status super onServicesDiscovered gatt status if
  • 从表A中选择B表中不存在的内容

    我正在尝试为 MySQL 编写一条 SELECT 语句 该语句从表 A 中选择表 B 中不存在的内容 例如 Table A BAND 1 2 3 4 5 Table B HATE 1 5 因此 如果表 A 是所有乐队 表 B 是我讨厌的乐队
  • xsl 使用键相乘

    抱歉 我不知道如何提问 我有 3 个 xml 文档 我有一个正在运行的 xsl 只是我无法弄清楚价格总额如何乘以数量 我的时间不多了 请帮忙 这是xsl
  • 在 SSIS 中的文件系统任务之后进行分支而不会使包失败

    如果文件系统任务 例如重命名 失败 例如文件不存在 则 SSIS 会认为这是一个错误 这意味着整个包失败 我可以通过使用脚本任务或将包的最大错误设置为多个来解决这个问题 将包的最大错误设置为多个的问题在于 如果包中的其他位置发生错误 则包不
  • PHPExcel 如何设置单元格名称?

    通常在 Excel 中 您可以为单元格指定特定名称 在 phpexcel 中如何做到这一点 开发人员文档的第 4 6 38 节描述了如何执行此操作 标题为 定义命名范围 的部分 objPHPExcel gt addNamedRange ne
  • 如何详细了解 Laravel 队列作业失败的原因?

    情况 我正在使用 Laravel 队列来处理大量媒体文件 单个作业预计需要几分钟 最多一个小时 我正在使用 Supervisor 来运行我的队列 并且一次运行 20 个进程 我的主管配置文件如下所示 program duplitron wo
  • AF_UNIX 套接字中缓冲区的最大长度

    我想知道 当使用套接字 AF UNIX 用C进行编程时 向套接字发送或从套接字接收数据时是否有任何限制 以字节为单位 您可以使用以下命令更改每个单独套接字连接的读取和写入缓冲区setsockopt http www opengroup or
  • 矩阵 - 如何从用户输入(行)创建矩阵?

    我想根据用户输入创建矩阵 如下所示 这是我的代码 flag True while flag num int input enter matrix dimension if num 0 print Finish flag False else
  • 如何在 LuisActionDialog 传递上下文中从一个意图跳转到另一个意图

    我正在使用 Microsoft Bot Framework LUIS 和LUIS动作绑定 https github com Microsoft BotBuilder Samples tree master CSharp Blog LUISA
  • 如何防止 CALayer(CATiledLayer 的子层)在缩放后更改其比例?

    我有一个用于显示 PDF 页面的 CATiledLayer 此 CATiledLayer 是我的 UIView 的图层类型 它是 UIScrollView 的子视图 我想在此页面上添加覆盖标记 因此 我将一个子层添加到我的 CATiledL
  • 如何确定上下文无关语法是否描述了常规语言?

    给定任意上下文无关语法 我如何检查它是否描述了常规语言 我不是在寻找考试 技巧 我正在寻找一种可以编写代码的万无一失的机械测试 如果有帮助 这里是我可能会收到的 CFG 作为输入的示例 具体来说 请注意 答案一定比仅仅寻找左递归或右递归复杂
  • 如何在另一个函数中使用带有参数的函数的返回值

    所有这些函数都位于 int main 之外 int func1 int x int v1 6 x return v1 the input argument will be 2 so v1 12 int func2 int v2 func1
  • $_POST[] 在 php 中不工作

    我已经开始学习PHP了 设法设置东西 我正在使用 php 版本 5 3 13 我正在尝试将一些信息发布到 html 表单并在 php 文件中接收它 为此 我使用 Post 变量 并且 php 文件的输出为空 下面是html代码
  • 如何记录Tomcat 7 JDBC连接池、连接创建

    尽管我们使用的是 Tomcat 7 JDBC 连接池 但我正在尝试调试似乎打开和关闭的数据库连接数量过多 当对数据源调用 getConnection 导致打开新连接而不是从池中借用现有连接时 如何记录 我知道有两种查看 Tomcat DB
  • 易失性读取和非易失性字段

    看完之后这个问题 https stackoverflow com questions 17108541 happens before relationships with volatile fields and synchronized b
  • 如何获取NSString的子字符串?

    如果我想从 NSString 获取值 value hello World value 我应该用什么 我想要的返回值是 hello World 选项1 NSString haystack value hello World value NSS
  • 使用 System.Text.Json 获取嵌套属性

    我正在与System Text Json在我的项目中 因为我正在处理大文件 所以也决定使用它来处理 GraphQL 响应 由于 GraphQL 的性质 有时我会得到高度嵌套的响应 这些响应不固定 并且映射到类没有意义 我通常需要检查响应的一