英文:
Is there a way to get list of specific element in JSON using C# and Newtonsoft
问题
Sure, here's the translated code portion:
我只想循环遍历 "RiskId" 和 "Occupants" 的列表并显示值。
如果我这样做....
```csharp
var jsonObj = (JObject)JsonConvert.DeserializeObject(jsonstring);
var jsonResult = jsonObj.SelectToken("Risks.RiskId").Select(m => m.Value<string>());
我得到以下错误
System.ArgumentNullException: '无法为 null 的值。参数名称: source'
<details>
<summary>英文:</summary>
Im trying to get a list of all the "Occupants" and "RiskId" from the JSON below using C# and Newtonsoft.
Not sure what I'm doing wrong here. Thanks for your help.
{
"Header": {
"MatchType": "Exact",
"TotalResultCount": 2,
"PreviousPageUrl": null,
"NextPageUrl": null,
"AvailableProductsForRequestedAddress": "https://prometrixapiuat.iso.com/uw/address/productList?City=MONTEBELLO&State=CA&StreetName=423+W+OLYMPIC+BLVD&Zip=90640"
},
"Risks": [
{
"RiskId": "64CX99016399",
"BuildingDescription": "MONTEBELLO PLASTICS INC (1S)",
"SurveyDates": {
"ScheduleAppliedDate": "04/21/1999",
"LatestPhoneSurveyDate": "",
"OnsiteSurveyDate": "05/01/1999"
},
"Location": {
"Latitude": null,
"Longitude": null,
"Address": {
"StreetAddress1": "423 W OLYMPIC BLVD",
"City": "MONTEBELLO",
"PostalCity": "MONTEBELLO",
"State": "CA",
"Zip": "90640",
"Zip4": "5225",
"County": "LOS ANGELES"
},
"AlternateAddresses": []
},
"Occupants": [
{
"Name": "MFG STORAGE - PACKAGING MATERIALS",
"OccupantId": "15"
}
],
"ProductListUrl": "https://prometrixapiuat.iso.com/uw/Risk/64CX99016399/ProductList",
"YearBuilt": 1960,
"FireProtectionArea": "MONTEBELLO"
},
{
"RiskId": "64CX99016400",
"BuildingDescription": "MONTEBELLO PLASTICS INC (1S)",
"SurveyDates": {
"ScheduleAppliedDate": "04/21/1999",
"LatestPhoneSurveyDate": "",
"OnsiteSurveyDate": "05/01/1999"
},
"Location": {
"Latitude": null,
"Longitude": null,
"Address": {
"StreetAddress1": "423 W OLYMPIC BLVD",
"City": "MONTEBELLO",
"PostalCity": "MONTEBELLO",
"State": "CA",
"Zip": "90640",
"Zip4": "5225",
"County": "LOS ANGELES"
},
"AlternateAddresses": []
},
"Occupants": [
{
"Name": "MFG STORAGE - PACKAGING MATERIALS",
"OccupantId": "15"
}
],
"ProductListUrl": "https://prometrixapiuat.iso.com/uw/Risk/64CX99016400/ProductList",
"YearBuilt": 1960,
"FireProtectionArea": "MONTEBELLO"
}
]
}
I would just like to loop through the list of "RiskId" and "Occupants" and display the value.
If I do ....
var jsonObj = (JObject)JsonConvert.DeserializeObject(jsonstring);
var jsonResult = jsonObj.SelectToken("Risks.RiskId").Select(m => m.Value<string>());
I'm getting below error
System.ArgumentNullException: 'Value cannot be null.
Parameter name: source'
</details>
# 答案1
**得分**: 1
变量jsonResult
将包含所有Risks
数组中的RiskId
属性,使用SelectTokens()
函数获取。
请注意:
"RiskId"
属性嵌套在对象数组Risks[*].RiskId
中,因此路径必须包含数组索引器,如[*]
或[0]
。[*]
选择所有RiskId
属性。- 由于
"RiskId"
属性位于数组中且不止一个,使用SelectTokens()
而不是SelectToken()
来获取它们。 - 如果不确定要选择属性的路径,可以使用递归下降运算符
..
选择所有具有该名称的属性,然后使用JToken.Path
获取每个属性的实际路径。
对于您的JSON,var paths = jsonObj.SelectTokens("..RiskId").Select(m => m.Path).ToList();
返回
[ "Risks[0].RiskId", "Risks[1].RiskId" ]
从中您可以看到,在原始查询中应该使用的正确路径是
"Risks[*].RiskId"
。
演示链接:https://dotnetfiddle.net/Lwrvdv
<details>
<summary>英文:</summary>
You may do:
var jsonResult = jsonObj.SelectTokens("Risks[*].RiskId")
.Select(m => m.Value<string>())
.ToList();
Notes:
1. The `"RiskId"` properties are nested in an array of objects `Risks[*].RiskId`, thus an array indexer such as `[*]` or `[0]` must be included in the path. `[*]` selects **all** `RiskId` properties.
2. Since the `"RiskId"` properties are in an array and there is more than one, use [`SelectTokens()`](https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JToken_SelectTokens.htm) rather than `SelectToken()` to get them all.
3. If you are unsure of the path to use to select a property by name, you may use the **recursive descent** operator `..` to select all properties with that name, and then use [`JToken.Path`](https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Linq_JToken_Path.htm) to get the actual path of each.
Thus, for your JSON,
```
var paths = jsonObj.SelectTokens("...RiskId").Select(m => m.Path).ToList();
```
Returns
```json
[
"Risks[0].RiskId",
"Risks[1].RiskId"
]
```
From which you can see that the correct path to use in the original query should have been `"Risks[*].RiskId"`.
Demo here: https://dotnetfiddle.net/Lwrvdv
</details>
# 答案2
**得分**: 1
以下是代码的中文翻译:
```csharp
昨天我向你展示了这种类型的代码
JArray risks = (JArray) JObject.Parse(jsonstring)["Risks"];
var riskId = risks.Select(r => (string) r["RiskId"]).FirstOrDefault(); // "64CX99016400"
JArray occupants = risks.Select(r => (JArray) r["Occupants"]).FirstOrDefault());
更新
在 @dbc 更新后,如果你有多个风险项,只需移除FirstOrDefault()
string[] riskIds = risks.Select(r => (string) r["RiskId"]);
Response.Write(string.Join(", ", riskIds)); // "64CX99016399, 64CX99016400"
List<JArray> occupants = risks.Select(r => (JArray) r["Occupants"]).ToList();
int[] occupantIds = occupants.SelectMany(o =>
o.Select(o => (int) o["OccupantId"])).ToArray();
Response.Write(string.Join(", ", occupantIds)); // "15, 15";
英文:
I showed you this kind of code yesterday
JArray risks = (JArray) JObject.Parse(jsonstring)["Risks"];
var riskId = risks.Select(r => (string) r["RiskId"] ).FirstOrDefault(); // "64CX99016400"
JArray occupants = risks.Select(r => (JArray) r["Occupants"] ).FirstOrDefault());
UPDATE
after @dbc update, if you can have several risks items, just remove firstordefault()
string[] riskIds = risks.Select(r => (string) r["RiskId"] );
Response.Write(string.Join(", ",riskIds)); // "64CX99016399, 64CX99016400"
List<JArray> occupants = risks.Select(r => (JArray) r["Occupants"] ).ToList();
int[] occupantIds = occupants.SelectMany(o =>
o.Select(o => (int)o["OccupantId"])).ToArray();
Response.Write(string.Join(", ",occupantIds)); // "15, 15";
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论