LINQ to JSON - 查询数组
LINQ to JSON - Querying an array
我需要 select 个在 json 数组中有“3”的用户。
{
"People":[
{
"id" : "123",
"firstName" : "Bill",
"lastName" : "Gates",
"roleIds" : {
"int" : ["3", "9", "1"]
}
},
{
"id" : "456",
"firstName" : "Steve",
"lastName" : "Jobs",
"roleIds" : {
"int" : ["3", "1"]
}
},
{
"id" : "789",
"firstName" : "Elon",
"lastName" : "Musk",
"roleIds" : {
"int" : ["3", "7"]
}
},
{
"id" : "012",
"firstName" : "Agatha",
"lastName" : "Christie",
"roleIds" : {
"int" : "2"
}
}
]}
最后,我的结果应该是 Elon Musk 和 Steve Jobs。这是我使用的代码(和其他变体):
var roleIds = pplFeed["People"]["roleIds"].Children()["int"].Values<string>();
var resAnAssocInfo = pplFeed["People"]
.Where(p => p["roleIds"].Children()["int"].Values<string>().Contains("3"))
.Select(p => new
{
id = p["id"],
FName = p["firstName"],
LName = p["lastName"]
}).ToList();
我收到以下错误:
"Accessed JArray values with invalid key value: "roleIds". Int32 array index expected"
我把 .Values<string>()
改成 .Values<int>()
还是不行。
我做错了什么?
你很接近。将您的 Where
子句更改为:
.Where(p => p["roleIds"].Children()["int"].Values<string>().Contains("3"))
对此:
.Where(p => p["roleIds"]["int"].Children().Contains("3"))
你会得到你想要的结果(尽管你的示例数据中实际上有三个用户角色 ID 为 "3"
,而不是两个)。
但是,您可能会遇到另一个问题,此代码仍然无法解决该问题。您会注意到,对于 Agatha Christie,int
的值不像其他数组那样是一个数组,它是一个简单的字符串。如果该值有时是一个数组,有时不是,那么您需要一个可以同时处理这两种情况的 where 子句。这样的事情应该有效:
.Where(p => p["roleIds"]["int"].Children().Contains(roleId) ||
p["roleIds"]["int"].ToString() == roleId)
...其中 roleId
是包含您要查找的 ID 的字符串。
Fiddle: https://dotnetfiddle.net/Zr1b6R
问题是并非所有对象都遵循相同的接口。该列表中的最后一项在 roleIds.int
属性 中有一个字符串值,而所有其他项都有一个数组。您需要规范化 属性 然后进行检查。如果都是数组就最简单了
你应该可以做到这一点:
var roleId = "3";
var query =
from p in pplFeed["People"]
let roleIds = p.SelectToken("roleIds.int")
let normalized = roleIds.Type == JTokenType.Array ? roleIds : new JArray(roleIds)
where normalized.Values().Contains(roleId)
select new
{
id = p["id"],
FName = p["firstName"],
LName = p["lastName"],
};
我需要 select 个在 json 数组中有“3”的用户。
{
"People":[
{
"id" : "123",
"firstName" : "Bill",
"lastName" : "Gates",
"roleIds" : {
"int" : ["3", "9", "1"]
}
},
{
"id" : "456",
"firstName" : "Steve",
"lastName" : "Jobs",
"roleIds" : {
"int" : ["3", "1"]
}
},
{
"id" : "789",
"firstName" : "Elon",
"lastName" : "Musk",
"roleIds" : {
"int" : ["3", "7"]
}
},
{
"id" : "012",
"firstName" : "Agatha",
"lastName" : "Christie",
"roleIds" : {
"int" : "2"
}
}
]}
最后,我的结果应该是 Elon Musk 和 Steve Jobs。这是我使用的代码(和其他变体):
var roleIds = pplFeed["People"]["roleIds"].Children()["int"].Values<string>();
var resAnAssocInfo = pplFeed["People"]
.Where(p => p["roleIds"].Children()["int"].Values<string>().Contains("3"))
.Select(p => new
{
id = p["id"],
FName = p["firstName"],
LName = p["lastName"]
}).ToList();
我收到以下错误:
"Accessed JArray values with invalid key value: "roleIds". Int32 array index expected"
我把 .Values<string>()
改成 .Values<int>()
还是不行。
我做错了什么?
你很接近。将您的 Where
子句更改为:
.Where(p => p["roleIds"].Children()["int"].Values<string>().Contains("3"))
对此:
.Where(p => p["roleIds"]["int"].Children().Contains("3"))
你会得到你想要的结果(尽管你的示例数据中实际上有三个用户角色 ID 为 "3"
,而不是两个)。
但是,您可能会遇到另一个问题,此代码仍然无法解决该问题。您会注意到,对于 Agatha Christie,int
的值不像其他数组那样是一个数组,它是一个简单的字符串。如果该值有时是一个数组,有时不是,那么您需要一个可以同时处理这两种情况的 where 子句。这样的事情应该有效:
.Where(p => p["roleIds"]["int"].Children().Contains(roleId) ||
p["roleIds"]["int"].ToString() == roleId)
...其中 roleId
是包含您要查找的 ID 的字符串。
Fiddle: https://dotnetfiddle.net/Zr1b6R
问题是并非所有对象都遵循相同的接口。该列表中的最后一项在 roleIds.int
属性 中有一个字符串值,而所有其他项都有一个数组。您需要规范化 属性 然后进行检查。如果都是数组就最简单了
你应该可以做到这一点:
var roleId = "3";
var query =
from p in pplFeed["People"]
let roleIds = p.SelectToken("roleIds.int")
let normalized = roleIds.Type == JTokenType.Array ? roleIds : new JArray(roleIds)
where normalized.Values().Contains(roleId)
select new
{
id = p["id"],
FName = p["firstName"],
LName = p["lastName"],
};