C# 如何使用System.Text.json从一些json中读取简单值?

C# 如何使用System.Text.json从一些json中读取简单值?,c#,.net-core,system.text.json,C#,.net Core,System.text.json,我有这个json {"id":"48e86841-f62c-42c9-ae20-b54ba8c35d6d"} 如何从中提取48e86841-f62c-42c9-ae20-b54ba8c35d6d?我能找到的所有例子都表明 var o = System.Text.Json.JsonSerializer.Deserialize<some-type>(json); o.id // <- here's the ID! 这确实有效-但是有更好的方法吗?您可以反序列化到字典中: var

我有这个json

{"id":"48e86841-f62c-42c9-ae20-b54ba8c35d6d"}
如何从中提取
48e86841-f62c-42c9-ae20-b54ba8c35d6d
?我能找到的所有例子都表明

var o = System.Text.Json.JsonSerializer.Deserialize<some-type>(json);
o.id // <- here's the ID!

这确实有效-但是有更好的方法吗?

您可以反序列化到
字典中:

var dict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(json)
var dict=System.Text.Json.JsonSerializer.Deserialize(Json)

或者只是反序列化到
对象
,这将产生一个可以调用的
JsonElement

我最近将一个项目从ASP.NET Core 2.2迁移到了3,这给我带来了不便。在我们的团队中,我们重视精益依赖,因此我们试图避免将Newtonsoft.JSON包含在后面,并尝试使用
System.Text.JSON
。我们还决定不只是在JSON序列化中使用大量POCO对象,因为我们的后端模型比Web API所需的更复杂。此外,由于非平凡的行为封装,后端模型无法轻松用于序列化/反序列化JSON字符串

我知道
System.Text.Json
应该比Newtonsoft.Json快,但我相信这与特定POCO类的ser/deser有很大关系。无论如何,速度不在我们这个决定的赞成/反对名单上,所以YMMV

长话短说,目前我编写了一个小型动态对象包装器,它从System.Text.Json中解包
jsonement
s,并尽可能地转换/转换。典型的用法是将请求主体作为动态对象读取。同样,我非常肯定这种方法会扼杀任何速度提升,但这并不是我们的用例所关心的

这是一节课:

    public class ReflectionDynamicObject : DynamicObject {
        public JsonElement RealObject { get; set; }

        public override bool TryGetMember (GetMemberBinder binder, out object result) {
            // Get the property value
            var srcData = RealObject.GetProperty (binder.Name);

            result = null;

            switch (srcData.ValueKind) {
                case JsonValueKind.Null:
                    result = null;
                    break;
                case JsonValueKind.Number:
                    result = srcData.GetDouble ();
                    break;
                case JsonValueKind.False:
                    result = false;
                    break;
                case JsonValueKind.True:
                    result = true;
                    break;
                case JsonValueKind.Undefined:
                    result = null;
                    break;
                case JsonValueKind.String:
                    result = srcData.GetString ();
                    break;
                case JsonValueKind.Object:
                    result = new ReflectionDynamicObject {
                        RealObject = srcData
                    };
                    break;
                case JsonValueKind.Array:
                    result = srcData.EnumerateArray ()
                        .Select (o => new ReflectionDynamicObject { RealObject = o })
                        .ToArray ();
                    break;
            }

            // Always return true; other exceptions may have already been thrown if needed
            return true;
        }
    }
这是一个解析请求主体的示例用法-一部分位于所有WebAPI控制器的基类中,该基类将主体作为动态对象公开:

    [ApiController]
    public class WebControllerBase : Controller {

        // Other stuff - omitted

        protected async Task<dynamic> JsonBody () {
            var result = await JsonDocument.ParseAsync (Request.Body);
            return new ReflectionDynamicObject {
                RealObject = result.RootElement
            };
        }
    }
[ApiController]
公共类网络控制器数据库:控制器{
//其他材料-省略
受保护的异步任务JsonBody(){
var result=await JsonDocument.ParseAsync(Request.Body);
返回新的ReflectionDynamicObject{
RealObject=result.RootElement
};
}
}
并可在实际控制器中使用,如下所示:

//[...]
    [HttpPost ("")]
    public async Task<ActionResult> Post () {
        var body = await JsonBody ();
        var name = (string) body.Name;
        //[...]
    }
//[...]
/[…]
[HttpPost(“”)
公共异步任务发布(){
var body=await JsonBody();
变量名称=(字符串)body.name;
//[...]
}
//[...]

如果需要,您可以根据需要集成对GUID或其他特定数据类型的解析,而我们都在等待官方/框架认可的解决方案。

更新到.NET Core 3.1以支持

public static dynamic FromJson(this string json, JsonSerializerOptions options = null)
    {
        if (string.IsNullOrEmpty(json))
            return null;

        try
        {
            return JsonSerializer.Deserialize<ExpandoObject>(json, options);
        }
        catch
        {
            return null;
        }
    }
public static dynamic FromJson(此字符串为json,JsonSerializerOptions options=null)
{
if(string.IsNullOrEmpty(json))
返回null;
尝试
{
返回JsonSerializer.Deserialize(json,选项);
}
抓住
{
返回null;
}
}

在System.Text.Json(.NET Core 3+)中解析字符串的实际方法


您可以使用以下扩展方法查询“xpath”之类的数据


你能使用像NethOpthon的JSON这样的第三方库吗?不,我们放弃了NethtSoStor,因为它有多慢。我不认为我添加的是一个答案。<代码>字典<代码>也不是一个坏的选择。“或者只是反序列化到一个对象,它将产生一个JSONE元素,你可以调用它。你能给我举个例子吗?使用System.Text.Json;var json=JsonSerializer。反序列化(json)为JsonElement?;var tmp=json?.GetProperty(“id”)我认为您也可以这样做:var je_root=JsonSerializer.Deserialize(jsonstr);然后像这样访问它:int myvalue=je_root.GetProperty(“MyProperty”).GetProperty(“MySubProperty”).GetInt32()@Muflix-如果需要测试属性是否存在,可以反序列化到JsonElement,然后使用:
JsonSerializer.Deserialize().TryGetProperty(“SomeProp”,out var元素)
JsonSerializer.Deserialize
不能帮助您从JsonValueKind中提取价值,升级.Net Core 3.1不会改变System.Text的行为。Json@Kuroro你是不对的,你可以很容易地将ExpandoObject转换为JsonElement,并获得所有对一级属性有效但对子级无效的东西。根据,当它超出范围时,需要将其强制转换为{System.Text.Json.JsonElement}
JsonDocument
,以防止内存泄漏。当您需要在文档的生存期之外使用
RootElement
时,必须使用它。
//[...]
    [HttpPost ("")]
    public async Task<ActionResult> Post () {
        var body = await JsonBody ();
        var name = (string) body.Name;
        //[...]
    }
//[...]
public static dynamic FromJson(this string json, JsonSerializerOptions options = null)
    {
        if (string.IsNullOrEmpty(json))
            return null;

        try
        {
            return JsonSerializer.Deserialize<ExpandoObject>(json, options);
        }
        catch
        {
            return null;
        }
    }
        var jsonStr = "{\"id\":\"48e86841-f62c-42c9-ae20-b54ba8c35d6d\"}";
        using var doc = JsonDocument.Parse(jsonStr);
        var root = doc.RootElement;
        var id = root.GetProperty("id").GetGuid();
public static string? JsonQueryXPath(this string value, string xpath, JsonSerializerOptions? options = null) => value.Deserialize<JsonElement>(options).GetJsonElement(xpath).GetJsonElementValue();

        
        public static JsonElement GetJsonElement(this JsonElement jsonElement, string xpath)
        {
            if (jsonElement.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
                return default;

            string[] segments = xpath.Split(new[] {'.'}, StringSplitOptions.RemoveEmptyEntries);

            foreach (var segment in segments)
            {
                if (int.TryParse(segment, out var index) && jsonElement.ValueKind == JsonValueKind.Array)
                {
                    jsonElement = jsonElement.EnumerateArray().ElementAtOrDefault(index);
                    if (jsonElement.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
                        return default;

                    continue;
                }

                jsonElement = jsonElement.TryGetProperty(segment, out var value) ? value : default;

                if (jsonElement.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
                    return default;
            }

            return jsonElement;
        }

        public static string? GetJsonElementValue(this JsonElement jsonElement) => jsonElement.ValueKind != JsonValueKind.Null &&
                                                                                   jsonElement.ValueKind != JsonValueKind.Undefined
            ? jsonElement.ToString()
            : default;
string 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""
                        }
                    }
                },
                {
                    ""node"": {
                        ""id"": ""gid://shopify/Product/123456789"",
                        ""featuredImage"": {
                            ""originalSrc"": ""https://cdn.shopify.com/s/files/1/0286/pic.jpg"",
                            ""id"": [
                                ""gid://shopify/ProductImage/123456789"",
                                ""gid://shopify/ProductImage/666666666""
                            ]
                        },
                        ""1"": {
                            ""name"": ""Tuanh""
                        }
                    }
                }
            ]
        }
        }
    }";

            System.Console.WriteLine(raw2.QueryJsonXPath("data.products.edges.0.node.featuredImage.id"));