JSON SelectToken 路径对于我想要的值来说太高(父)或太低(子)

JSON SelectToken Path Either Too High (Parent) or Too Low (Child) For Values I Want

我在 https://sandbox.api.dell.com/support/assetinfo/v4/ 查询 DellAPI 以获取扩展现场支持保修的结束日期作为 .NET 对象。但是我在定义我的 SelectToken 路径以处理戴尔的 JSON 结果时遇到了问题。

这是我正在使用的相关代码(没有戴尔API密钥和服务标签):

string Serial = device.dev_service_tag_serial;
var json = new WebClient().DownloadString(dellAPIPath + "getassetwarranty/" + Serial + "?apikey=" + dellAPIKey);
JObject jo = JObject.Parse(json);

foreach (JProperty x in jo.SelectToken("AssetWarrantyResponse[0].AssetEntitlementData"))
{
    JToken servicelevel = x.Value.SelectToken("ServiceLevelDescription");
    string servicelevelStr = servicelevel.ToString().ToLower();
    JToken entitlementtype = x.Value.SelectToken("EntitlementType");
    string entitlementtypeStr = entitlementtype.ToString().ToLower();

    if (servicelevelStr.Contains("onsite") && entitlementtypeStr.Contains("extended"))
    {
        JToken enddate = x.Value.SelectToken("EndDate");
        string enddateStr = enddate.ToString();
        device.dev_warranty_exp = DateTime.Parse(enddateStr);

    }

}

第一个 SelectToken 要么 return 为 NULL,要么是错误的令牌级别,具体取决于我如何更改它。

这是我正在使用的 Dell API JSON 结果的一个结果(将潜在的敏感值替换为数字的 Ones 和 As 的字母):

{{
  "AssetWarrantyResponse": [
    {
      "AssetHeaderData": {
        "BUID": "11",
        "ServiceTag": "11A11A1",
        "ShipDate": "2011-03-02T00:00:00",
        "CountryLookupCode": "US",
        "LocalChannel": "45",
        "CustomerNumber": "1111111",
        "ItemClassCode": "2N002",
        "IsDuplicate": false,
        "MachineDescription": "Latitude E6510",
        "OrderNumber": "111111111",
        "ParentServiceTag": null
      },
      "ProductHeaderData": {
        "SystemDescription": "Latitude E6510",
        "ProductId": "latitude-e6510",
        "ProductFamily": "Laptops",
        "LOB": "Latitude",
        "LOBFriendlyName": "Latitude"
      },
      "AssetEntitlementData": [
        {
          "StartDate": "2011-03-02T00:00:00",
          "EndDate": "2015-03-02T23:59:59",
          "ServiceLevelDescription": "Complete Care / Accidental Damage",
          "ServiceLevelCode": "CC",
          "ServiceLevelGroup": 11,
          "EntitlementType": "INITIAL",
          "ServiceProvider": "DELL",
          "ItemNumber": "908-5233"
        },
        {
          "StartDate": "2012-03-03T00:00:00",
          "EndDate": "2015-03-02T23:59:59",
          "ServiceLevelDescription": "ProSupport",
          "ServiceLevelCode": "TS",
          "ServiceLevelGroup": 8,
          "EntitlementType": "EXTENDED",
          "ServiceProvider": "DELL",
          "ItemNumber": "981-1533"
        },
        {
          "StartDate": "2012-03-03T00:00:00",
          "EndDate": "2015-03-02T23:59:59",
          "ServiceLevelDescription": "Onsite Service After Remote Diagnosis (Consumer Customer)/ Next Business Day Onsite After Remote Diagnosis (Commercial Customer)",
          "ServiceLevelCode": "ND",
          "ServiceLevelGroup": 5,
          "EntitlementType": "EXTENDED",
          "ServiceProvider": "QLX",
          "ItemNumber": "908-5163"
        },
        {
          "StartDate": "2011-03-02T00:00:00",
          "EndDate": "2012-03-02T23:59:59",
          "ServiceLevelDescription": "ProSupport",
          "ServiceLevelCode": "TS",
          "ServiceLevelGroup": 8,
          "EntitlementType": "INITIAL",
          "ServiceProvider": "DELL",
          "ItemNumber": "984-4000"
        },
        {
          "StartDate": "2011-03-02T00:00:00",
          "EndDate": "2012-03-02T23:59:59",
          "ServiceLevelDescription": "Onsite Service After Remote Diagnosis (Consumer Customer)/ Next Business Day Onsite After Remote Diagnosis (Commercial Customer)",
          "ServiceLevelCode": "ND",
          "ServiceLevelGroup": 5,
          "EntitlementType": "INITIAL",
          "ServiceProvider": "QLX",
          "ItemNumber": "926-2550"
        }
      ]
    }
  ],
  "InvalidFormatAssets": {
    "BadAssets": []
  },
  "InvalidBILAssets": {
    "BadAssets": []
  },
  "ExcessTags": {
    "BadAssets": []
  },
  "AdditionalInformation": null
}}

我只关心 AssetEntitlementData 位。对于服务级别包含 "onsite" 且权利类型包含 "extended" 的服务,我想 return EndDate 值。

任何人都可以引导我朝着正确的方向前进,关于我在 jo.SelectToken 路径上出错的地方吗?

除了 EndDate 之外,您似乎还需要知道 ItemNumber 以便了解与该服务级别和日期相关的计算机。所以至少有3条信息。

从 Parsing 获取数据相当简单,如果语法复杂的话:

var jobj = JObject.Parse(jstr);

//isolate the data group for shorter code
var jAssets = jobj["AssetWarrantyResponse"][0]["AssetEntitlementData"];  
// how many    
int assetCt = jAssets.Count();

for (int k = 0; k < assetCt; k++)
{ 
    Console.WriteLine("Item Number: {0}, End Date: {1}, Svc Lvl: {2}",
        jAssets[k]["ItemNumber"],
        DateTime.Parse(jAssets[k]["EndDate"].ToString()),
        jAssets[k]["ServiceLevelDescription"]);      
}

示例结果:

Item Number: 908-5233, End Date: 3/9/2015 11:59:59 PM, Svc Lvl: Complete Care / Accidental Damage
Item Number: 981-1533, End Date: 3/7/2015 11:59:59 PM, Svc Lvl: ProSupport
Item Number: 908-5163, End Date: 3/20/2015 11:59:59 PM, Svc Lvl: Onsite Service After Remote Diagnosis (Consumer Customer)/ Next Business Day Onsite After Remote Diagnosis (Commercial Customer)

  • 我更改了一些日期,因此我可以确定它选择了不同的日期
  • 仍然需要过滤到您想要的那个(只有一个有 EXTENDED 和 OnSite)。使用 NET 对象和反序列化更容易。

反序列化

给定一个 class 表示 AssetEntitlementData:

public class DellData
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string ServiceLevelDescription { get; set; }
    public string ServiceLevelCode { get; set; }
    public int ServiceLevelGroup { get; set; }
    public string EntitlementType { get; set; }
    public string ServiceProvider { get; set; }
    public string ItemNumber { get; set; }
}

您可以解析出该块并将其放入 filtered List<DellData>:

var jobj = JObject.Parse(jstr);

// deserialize and filter to just the ones you want:
List<DellData> data = JsonConvert.DeserializeObject<List<DellData>>(jAssets.ToString()).
            Where( k => (k.ServiceLevelGroup == 5) && (k.EntitlementType == "EXTENDED")).
            ToList();

请注意,这不是查找特定文本,而是查找 ServiceLevelGroup 5,因此如果他们更改说明(“On-Site”或“排除现场服务”),您的代码不会不要休息。打印结果:

foreach (DellData d in data)
{
    Console.WriteLine("Item Number: {0}, End Date: {1}, Svc Grp: {2}",
        d.ItemNumber,
        d.EndDate.ToString("yyyy-MM-dd"),
        d.ServiceLevelGroup);
}

结果:

Item Number: 867-5309, End Date: 2017-03-26, Svc Grp: 5
Item Number: 908-5163, End Date: 2015-03-20, Svc Grp: 5

我添加了一个符合条件的额外项目,因为一个样本很弱。