首页 > 解决方案 > 查询嵌套 JSON 结构以查找子数组中具有最小值的对象

问题描述

我有以下 JSON:

{
  "travelClasses": [
    {
      "fares": [
        {
          "referenceId": "a",
          "fare": {
            "tax": 48.99,
            "totalFare": 519.99,
            "currency": {
              "code": "USD",
              "exchangeRate": 1
            }
          }
        }
      ],
      "availableSeats": 9,
      "type": "Pro",
      "code": "B",
      "name": "UX"
    },
    {
      "fares": [
        {
          "referenceId": "b",
          "fare": {
            "tax": 98.99,
            "totalFare": 119.99,
            "currency": {
              "code": "USD",
              "exchangeRate": 1
            }
          }
        }
      ],
      "availableSeats": 9,
      "type": "Pro",
      "code": "C",
      "name": "UC"
    },
    {
      "fares": [
        {
          "referenceId": "c",
          "fare": {
            "tax": 48.99,
            "totalFare": 819.99,
            "currency": {
              "code": "USD",
              "exchangeRate": 1
            }
          }
        }
      ],
      "availableSeats": 9,
      "type": "Eco",
      "code": "X",
      "name": "US"
    }
  ]
}

我需要查询这个 JSON,然后我想检索具有最小值的对象totalFare。在我的示例中,第二个节点具有最小值totalFare,因此我需要使用类似.ToObject<TravelClass>().

{
  "fares": [
    {
      "referenceId": "b",
      "fare": {
        "tax": 98.99,
        "totalFare": 119.99,
        "currency": {
          "code": "USD",
          "exchangeRate": 1
        }
      }
    }
  ],
  "availableSeats": 9,
  "type": "Pro",
  "code": "C",
  "name": "UC"
}

我查看了有关查询 a的Newtonsoft 文档JObject,但我无法解决这个问题。

最后,这是我尝试过的 C# 代码:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            JObject o = JObject.Parse(@"{
              'travelClasses': [
                {
                  'fares': [
                    {
                      'referenceId': 'a',
                      'fare': {
                        'tax': 48.99,
                        'totalFare': 519.99,
                        'currency': {
                          'code': 'USD',
                          'exchangeRate': 1
                        }
                      }
                    }
                  ],
                  'availableSeats': 9,
                  'type': 'Pro',
                  'code': 'B',
                  'name': 'UX'
                },
                {
                  'fares': [
                    {
                      'referenceId': 'b',
                      'fare': {
                        'tax': 98.99,
                        'totalFare': 119.99,
                        'currency': {
                          'code': 'USD',
                          'exchangeRate': 1
                        }
                      }
                    }
                  ],
                  'availableSeats': 9,
                  'type': 'Pro',
                  'code': 'C',
                  'name': 'UC'
                },
                {
                  'fares': [
                    {
                      'referenceId': 'c',
                      'fare': {
                        'tax': 48.99,
                        'totalFare': 819.99,
                        'currency': {
                          'code': 'USD',
                          'exchangeRate': 1
                        }
                      }
                    }
                  ],
                  'availableSeats': 9,
                  'type': 'Eco',
                  'code': 'X',
                  'name': 'US'
                }
              ]
            }");

            var minFareTravelClassObject = o["travelClasses"]
                .Select(m => m.SelectToken("fares")
                .OrderByDescending(x => x["totalFare"]))
                .FirstOrDefault();     
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}

public partial class TravelClass
{
    [JsonProperty("fares")]
    public List<FareElement> Fares { get; set; }

    [JsonProperty("availableSeats")]
    public int AvailableSeats { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }

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

public partial class FareElement
{
    [JsonProperty("referenceId")]
    public string ReferenceId { get; set; }

    [JsonProperty("fare")]
    public FareFare Fare { get; set; }
}

public partial class FareFare
{
    [JsonProperty("tax")]
    public decimal Tax { get; set; }

    [JsonProperty("totalFare")]
    public decimal TotalFare { get; set; }

    [JsonProperty("currency")]
    public Currency Currency { get; set; }
}

public partial class Currency
{
    [JsonProperty("code")]
    public string Code { get; set; }

    [JsonProperty("exchangeRate")]
    public decimal ExchangeRate { get; set; }
}

标签: c#jsonjson.net

解决方案


由于您已经定义了接收数据的类,我建议对这些类进行反序列化并跳过JObject. 您只需要一个类来表示根级别:

public class RootObject
{
    [JsonProperty("travelClasses")]
    public List<TravelClass> TravelClasses { get; set; }
}

您可以像这样反序列化:

var root = JsonConvert.DeserializeObject<RootObject>(json);

从那里您可以使用 LINQ 查询找到TravelClass最低的TotalFare

var bestTravelClass = root.TravelClasses
    .SelectMany(tc => tc.Fares, (tc, f) => new { TravelClass = tc, f.Fare.TotalFare })
    .OrderBy(a => a.TotalFare)
    .Select(a => a.TravelClass)
    .FirstOrDefault();

小提琴:https ://dotnetfiddle.net/8WoW5J


推荐阅读