简体   繁体   English

C# LINQ 查询嵌套列表 JSON

[英]C# LINQ Query to List of Nested JSON

I have been attempting to create a LINQ query in C# which will allow me to create a List<> from different properties in the JSON string, which are of interest to me.我一直在尝试在 C# 中创建一个 LINQ 查询,这将允许我从 JSON 字符串中的不同属性创建一个 List<>,这是我感兴趣的。

I have attempted a number of different approaches of.Select() and.SelectMany() but always end up with creating an exception.我尝试了许多不同的方法 .Select() 和 .SelectMany() 但总是以创建异常而告终。 To unblock I have resorted to creating 2 or 3 independent Linq Queries which will extract the data I care about and then append these to a List.为了解除阻塞,我求助于创建 2 或 3 个独立的 Linq 查询,这些查询将提取我关心的数据,然后将 append 提取到一个列表中。

Of course, this is utterly ugly;当然,这非常丑陋。 and therefore I am here asking from some guidance on how to do this correctly.因此,我在这里询问有关如何正确执行此操作的一些指导。 I am not a professional developer, and IT Pro lost in DevOps;我不是专业的开发人员,IT Pro 迷失在 DevOps 中; so please be kind!所以请善待!

This is a sample of the JSON payload这是 JSON 有效载荷的示例

{
  "value": [
    {
      "name": "p-we1net-network-vnet",
      "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "westeurope",
      "tags": {
        "IaCVersion": "logsRetentionDays-20200505.02",
        "ConfigVersion": "1.0.0.0"
      },
      "properties": {
        "provisioningState": "Succeeded",
        "resourceGuid": "e7619105-bd1c-4110-b19f-f465c5743899",
        "addressSpace": {
          "addressPrefixes": [
            "99.111.0.0/22"
          ]
        },
        "dhcpOptions": {
          "dnsServers": []
        },
        "subnets": [
          {
            "name": "GatewaySubnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/subnets/GatewaySubnet",
            "properties": {
              "provisioningState": "Succeeded",
              "addressPrefix": "99.111.0.0/24",
              "routeTable": {
                "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/routeTables/p-we1net-network-vnet-GatewaySubnet-rt"
              },
              "ipConfigurations": [
                {
                  "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworkGateways/p-we1net-network-vpn/ipConfigurations/vnetGatewayConfig"
                }
              ],
              "serviceEndpoints": [
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.Storage",
                  "locations": [
                    "westeurope",
                    "northeurope"
                  ]
                }
              ],
              "delegations": [],
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            },
            "type": "Microsoft.Network/virtualNetworks/subnets"
          },
          {
            "name": "AzureFirewallSubnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/subnets/AzureFirewallSubnet",
            "properties": {
              "provisioningState": "Succeeded",
              "addressPrefix": "99.111.1.0/24",
              "routeTable": {
                "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/routeTables/p-we1net-network-vnet-AzureFirewallSubnet-rt"
              },
              "ipConfigurations": [
                {
                  "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/azureFirewalls/p-we1net-network-fw/azureFirewallIpConfigurations/p-we1net-network-fw-pip001"
                }
              ],
              "serviceEndpoints": [
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.AzureActiveDirectory",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.AzureCosmosDB",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.CognitiveServices",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.ContainerRegistry",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.EventHub",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.KeyVault",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.ServiceBus",
                  "locations": [
                    "*"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.Sql",
                  "locations": [
                    "westeurope"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.Storage",
                  "locations": [
                    "westeurope",
                    "northeurope"
                  ]
                },
                {
                  "provisioningState": "Succeeded",
                  "service": "Microsoft.Web",
                  "locations": [
                    "*"
                  ]
                }
              ],
              "delegations": [],
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            },
            "type": "Microsoft.Network/virtualNetworks/subnets"
          }
        ],
        "virtualNetworkPeerings": [
          {
            "name": "p-we1waf-network-vnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/virtualNetworkPeerings/p-we1waf-network-vnet",
            "properties": {
              "provisioningState": "Succeeded",
              "resourceGuid": "dee9953a-82b7-0f66-01ad-c11f82585928",
              "peeringState": "Connected",
              "remoteVirtualNetwork": {
                "id": "/subscriptions/guid/resourceGroups/p-we1waf-network/providers/Microsoft.Network/virtualNetworks/p-we1waf-network-vnet"
              },
              "allowVirtualNetworkAccess": true,
              "allowForwardedTraffic": false,
              "allowGatewayTransit": true,
              "useRemoteGateways": false,
              "doNotVerifyRemoteGateways": false,
              "remoteAddressSpace": {
                "addressPrefixes": [
                  "99.111.4.0/22"
                ]
              },
              "routeServiceVips": {}
            },
            "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings"
          },
          {
            "name": "p-we1dc-network-vnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/virtualNetworkPeerings/p-we1dc-network-vnet",
            "properties": {
              "provisioningState": "Succeeded",
              "resourceGuid": "e3fad777-dac9-037a-1814-3609d6a3286c",
              "peeringState": "Connected",
              "remoteVirtualNetwork": {
                "id": "/subscriptions/guid/resourceGroups/p-we1dc-network/providers/Microsoft.Network/virtualNetworks/p-we1dc-network-vnet"
              },
              "allowVirtualNetworkAccess": true,
              "allowForwardedTraffic": false,
              "allowGatewayTransit": true,
              "useRemoteGateways": false,
              "doNotVerifyRemoteGateways": false,
              "remoteAddressSpace": {
                "addressPrefixes": [
                  "99.111.8.0/25"
                ]
              },
              "routeServiceVips": {}
            },
            "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings"
          },
          {
            "name": "p-we1rmt-network-vnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/virtualNetworkPeerings/p-we1rmt-network-vnet",
            "properties": {
              "provisioningState": "Succeeded",
              "resourceGuid": "2e9593b3-d730-0251-1e39-87d3b767cc06",
              "peeringState": "Connected",
              "remoteVirtualNetwork": {
                "id": "/subscriptions/guid/resourceGroups/p-we1rmt-network/providers/Microsoft.Network/virtualNetworks/p-we1rmt-network-vnet"
              },
              "allowVirtualNetworkAccess": true,
              "allowForwardedTraffic": false,
              "allowGatewayTransit": true,
              "useRemoteGateways": false,
              "doNotVerifyRemoteGateways": false,
              "remoteAddressSpace": {
                "addressPrefixes": [
                  "99.111.8.128/25"
                ]
              },
              "routeServiceVips": {}
            },
            "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings"
          },
          {
            "name": "t-tstsp1-network-vnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/virtualNetworkPeerings/t-tstsp1-network-vnet",
            "properties": {
              "provisioningState": "Succeeded",
              "resourceGuid": "4ed7d2c0-ecba-06ae-0cc5-90595382193c",
              "peeringState": "Connected",
              "remoteVirtualNetwork": {
                "id": "/subscriptions/guid/resourceGroups/t-tstsp1-network/providers/Microsoft.Network/virtualNetworks/t-tstsp1-network-vnet"
              },
              "allowVirtualNetworkAccess": true,
              "allowForwardedTraffic": false,
              "allowGatewayTransit": true,
              "useRemoteGateways": false,
              "doNotVerifyRemoteGateways": false,
              "remoteAddressSpace": {
                "addressPrefixes": [
                  "99.111.9.0/25"
                ]
              },
              "routeServiceVips": {}
            },
            "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings"
          },
          {
            "name": "t-tstsp2-network-vnet",
            "id": "/subscriptions/guid/resourceGroups/p-we1net-network/providers/Microsoft.Network/virtualNetworks/p-we1net-network-vnet/virtualNetworkPeerings/t-tstsp2-network-vnet",
            "properties": {
              "provisioningState": "Succeeded",
              "resourceGuid": "8a4eb533-d883-0725-13a8-ebd4d3973fbe",
              "peeringState": "Connected",
              "remoteVirtualNetwork": {
                "id": "/subscriptions/guid/resourceGroups/t-tstsp2-network/providers/Microsoft.Network/virtualNetworks/t-tstsp2-network-vnet"
              },
              "allowVirtualNetworkAccess": true,
              "allowForwardedTraffic": false,
              "allowGatewayTransit": true,
              "useRemoteGateways": false,
              "doNotVerifyRemoteGateways": false,
              "remoteAddressSpace": {
                "addressPrefixes": [
                  "99.111.9.128/25"
                ]
              },
              "routeServiceVips": {}
            },
            "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings"
          }
        ],
        "enableDdosProtection": false,
        "enableVmProtection": false
      }
    }
  ]
}

What I am looking to extract to a list is the following nodes, to an object/class我要提取到列表中的是以下节点,对象/类

NetworkName (string)网络名称(字符串)
["Value"][0][Name] [“值”][0][名称]

HostNetwork (List) ["Value"][0][properties][addressPrefixes] HostNetwork(列表) ["Value"][0][properties][addressPrefixes]

PeeredNets (List) ["Value"][0][properties][virtualNetworkPeerings][x][properties][remoteAddressSpace][addressPrefixes] PeeredNets (List) ["Value"][0][properties][virtualNetworkPeerings][x][properties][remoteAddressSpace][addressPrefixes]

Now, for the embarrassing part, this is the code I created;现在,对于令人尴尬的部分,这是我创建的代码; feel free to redact this: :)随意编辑这个::)

try {
          JObject root = JObject.Parse(response);

          // Get the VNET Name
          cidrData.name = root["value"][0]["name"].ToString();
          Console.WriteLine($"Name: {cidrData}");

          // Get the Supernets
          JArray superNet = new JArray(root["value"][0]["properties"]["addressSpace"]["addressPrefixes"]);
          cidrData.supernet = superNet.FirstOrDefault()[0].ToString();

          foreach(var item in superNet){
            Console.WriteLine($"SuperNets: {item[0].ToString()}");
          }

          // Get the Subnets
          cidrData.subnets = new List<string>();

          var networkPeeringList = JObject.Parse(response)
            .Descendants()
            .Where(x => x is JObject)
            .Where(x => x["name"] != null )
            .Select(x => new {
              name = (string)x["name"],
              data = (string)x["properties"].ToString()
              })
            .ToList();

          foreach (var peeredNetwork in networkPeeringList)
          {
            Console.WriteLine($" {peeredNetwork.name}");

            var netData = JObject.Parse(peeredNetwork.data)
              .Descendants()
              .Where(x => x is JObject)
              .Where(x => x["addressPrefixes"] != null )
              .Select(x => new {
                name = x["addressPrefixes"]
              })
              .ToList();

            foreach (var record in netData) {
              var subnet = record.name[0].ToString();
              cidrData.subnets.Add(subnet);
              Console.WriteLine($" {subnet}");
            }

          }

        }

Can anyone tell me how to do this more elegantly;谁能告诉我如何更优雅地做到这一点; preferably with a single LINQ query to cheery pick the values from the JSON?最好使用单个 LINQ 查询来愉快地从 JSON 中挑选值?

Cheers干杯

Here's the simple solution you can try.这是您可以尝试的简单解决方案。 First, map the JSON to Model(POCO) and deserialize the JSON apply LINQ and get an object with all your values. First, map the JSON to Model(POCO) and deserialize the JSON apply LINQ and get an object with all your values.

Model classes for properties you want from JSON. Model 类,用于您想要从 JSON 获得的属性。

public partial class Values
{
[JsonProperty("value")] public List<Value> Value { get; set; }
}

public partial class Value
{
[JsonProperty("name")] public string Name { get; set; }

[JsonProperty("properties")] public ValueProperties Properties { get; set; }
}

public partial class ValueProperties
{
[JsonProperty("addressSpace")] public AddressSpace AddressSpace { get; set; }

[JsonProperty("virtualNetworkPeerings")]
public List<VirtualNetworkPeering> VirtualNetworkPeerings { get; set; }
}

public partial class AddressSpace
{
[JsonProperty("addressPrefixes")] public List<string> AddressPrefixes { get; set; }
}


public partial class VirtualNetworkPeering
{
[JsonProperty("properties")] public VirtualNetworkPeeringProperties Properties { get; set; }
}

public partial class VirtualNetworkPeeringProperties
{
[JsonProperty("remoteAddressSpace")] public AddressSpace RemoteAddressSpace { get; set; }
}

Deserialize the JSON and get desired properites:反序列化 JSON 并获得所需的属性:

var values = JsonConvert.DeserializeObject<Values>(json);
var desiredValues = values.Value
        .Select(x => new
        {
          NetworkName = x.Name,
          HostNetwork = x.Properties.AddressSpace.AddressPrefixes.Select(address => address).ToList(),
          PeeredNets = x.Properties.VirtualNetworkPeerings
            .SelectMany(peering => peering.Properties.RemoteAddressSpace.AddressPrefixes).Select(address => address).ToList()
        }).ToList();

Note This requires you to install Newtonsoft.Json注意这需要您安装Newtonsoft.Json

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM