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
我添加了一个符合条件的额外项目,因为一个样本很弱。
我在 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
我添加了一个符合条件的额外项目,因为一个样本很弱。