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

编程入门 行业动态 更新时间:2024-10-26 06:29:35
本文介绍了使用System.Text.Json获取嵌套属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我在处理大型文件时正在使用项目中的 System.Text.Json ,因此也决定使用它来处理GraphQL响应.

I am working with System.Text.Json in my project as I am processing large files so also decided to use it for processing GraphQL responses.

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

Due to the nature of GraphQL sometimes I get highly nested responses that are not fixed and don't make sense to map to a class. I usually need to check a few properties on the response.

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

My issue is with JsonElement. To check nested properties feels very clumsy and I feel like there should be a better way to approach this.

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

For example take my below code simulating a response I get. I just want to check if 2 properties exist (id & originalSrc) and if they do get their value but it feels like I have made a meal of the code. Is there a better/clearer/more succinct way to write this?

var raw = @"{ ""data"": { ""products"": { ""edges"": [ { ""node"": { ""id"": ""gid://shopify/Product/4534543543316"", ""featuredImage"": { ""originalSrc"": ""cdn.shopify/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 }

这不是疯狂的代码,但是检查少数几个属性是如此普遍,我希望有一种更简洁,更易读的方法.

It is not a crazy amount of code but checking a handful of properties is so common I would like a cleaner more readble approach.

推荐答案

您可以添加几个扩展方法,这些扩展方法通过属性名称或数组索引访问子 JsonElement 值,如果返回则为可空值找不到:

You could add a couple of extension methods that access a child JsonElement value by property name or array index, returning a nullable value if not found:

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; var value = element.EnumerateArray().ElementAtOrDefault(index); return value.ValueKind != JsonValueKind.Undefined ? value : (JsonElement?)null; } }

现在可以使用空条件运算符 ?. :

Now calls to access nested values can be chained together using the null-conditional operator ?.:

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.

注意:

  • 如果传入的元素不是预期的类型(对象或数组或null/missing),则上述扩展方法将引发异常.您可以放松对 ValueKind ,如果您从不希望出现意外值类型的异常.

  • The extension methods above will throw an exception if the incoming element is not of the expected type (object or array or null/missing). You could loosen the checks on ValueKind if you never want an exception on an unexpected value type.

有一个开放的API增强请求 将JsonPath支持添加到JsonDocument/JsonElement#31068 .通过 JSONPath 进行的查询将使这种事情变得更容易.

There is an open API enhancement request Add JsonPath support to JsonDocument/JsonElement #31068. Querying via JSONPath, if implemented, would make this sort of thing easier.

演示小提琴此处.

更多推荐

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

本文发布于:2023-11-03 13:03:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1555200.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:嵌套   属性   System   Text   Json

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!