【问题标题】:Is there a more elegant way to get specific value from JSON object using system.text.json有没有更优雅的方法来使用 system.text.json 从 JSON 对象中获取特定值
【发布时间】:2020-06-17 13:10:16
【问题描述】:

考虑这个 Json 对象:

{
    "main": {
        "2058": {
            "id": "2058",
            "name": "foo",
            "attrib1": "17",
            "domain": "somewhere.net",
            "enabled": "1",
            "permissions": [
                "admin",
                "user",
                "guest",
                "vpn",
                "power"
            ]
        }
    },
    "validate": {
        "2058": {
            "id": "2058",
            "name": "foo",
            "attrib1": "17",
            "domain": "somewhere.net",
            "enabled": "1",
            "permissions": [
                "admin",
                "user",
                "guest",
                "vpn",
                "power"
            ]
        }
    },
    "result": "ok"
}

在“启用”和“权限”之间,我遗漏了好几百对。 “验证”部分是“主要”的精确副本,“结果”是结果。

我想从主要部分获取 2 个特定值。 “id”和“域”。我使用以下代码来执行此操作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;

namespace JsonParse
{
    class Program
    {
        static void Main()
        {
            string json = "{" +
                "\"main\":{" +
                    "\"2058\":{" +
                        "\"id\":\"2058\"," +
                        "\"name\":\"foo\"," +
                        "\"attrib1\":\"17\"," +
                        "\"domain\":\"somewhere.net\"," +
                        "\"enabled\":\"1\"," +
                        "\"permissions\":[\"admin\",\"user\",\"guest\",\"vpn\",\"power\"]" +
                    "}" +
                "}," +
                "\"validate\":{" +
                    "\"2058\":{" +
                        "\"id\":\"2058\"," +
                        "\"name\":\"foo\"," +
                        "\"attrib1\":\"17\"," +
                        "\"domain\":\"somewhere.net\"," +
                        "\"enabled\":\"1\"," +
                        "\"permissions\":[\"admin\",\"user\",\"guest\",\"vpn\",\"power\"]" +
                    "}" +
                "}," +
                "\"result\":\"ok\"" +
            "}";

            foreach (KeyValuePair<string, object> item in JsonSerializer.Deserialize<Dictionary<string, object>>(json))
            {
                if (item.Key == "main")
                {
                    Dictionary<string, object> pairs = JsonSerializer.Deserialize<Dictionary<string, object>>(item.Value.ToString());
                    Dictionary<string, object> pairs1 = JsonSerializer.Deserialize<Dictionary<string, object>>(pairs.First().Value.ToString());
                    foreach (KeyValuePair<string, object> valuePair in pairs1)
                    {
                        if (valuePair.Key == "id" || valuePair.Key == "domain")
                        {
                            Console.WriteLine("Key: " + valuePair.Key + "\nValue: " + valuePair.Value);
                        }
                    }
                }
            }
        }
    }
}

由此,我得到“2058”和“somewhere.net”,但是有没有更优雅的方式来获取值而不是反序列化 3 次?

【问题讨论】:

标签: c# json .net-core system.text.json


【解决方案1】:

如果您使用System.Text.Json API,您可以先将您的JSON 解析为JsonDocument,然后枚举其属性。先获取main对象,然后将其子属性展平,通过iddomain名称查找所需值

using var document = JsonDocument.Parse(jsonString);

var main = document.RootElement.EnumerateObject().FirstOrDefault(p => p.Name == "main");
var properties = main.Value.EnumerateObject().SelectMany(p => p.Value.EnumerateObject()).ToList();
var id = properties.FirstOrDefault(p => p.Name == "id").Value.GetString();
var domain = properties.FirstOrDefault(p => p.Name == "domain").Value.GetString();

【讨论】:

    【解决方案2】:

    如果您只需要 main 属性,您可以使用 json path 通过 Newtonsoft Json.NET 选择所有“电源”:

    var pairs = JObject.Parse(js).SelectTokens("$.main.*")
        .Select(j => (id:j["id"],domain: j["domain"]))
        .ToList();
    

    或者只是反序列化为相应的结构(使用System.Text.Json 或Newtonsoft):

    class MyClass
    {
        public Dictionary<string, InnerClass> main { get; set; }
    }
    
    class InnerClass
    {
        public string id { get; set; }
        public string domain { get; set; }
    }
    
    ICollection<InnerClass> mains= JsonSerializer.Deserialize<MyClass>(js).main.Values; // System.Text.Json
    

    【讨论】:

    • OP 正在使用system.text.json
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多