查询嵌套的JSON结构以在子数组中找到具有最小值的对象

时间:2018-11-28 22:42:52

标签: c# json json.net

我有以下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>()之类的内容来检索以下JSON对象。

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

我检查了Newtonsoft documentation有关查询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; }
}

1 个答案:

答案 0 :(得分:1)

由于您已经定义了一些类来接收数据,因此建议您反序列化这些类并跳过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