ASP.NET Core MVC中Microsoft.ClearScript.V8的Linq Where过滤JSON失效求助
问题分析与解决
你的代码存在几个关键问题导致Linq Where无法正常生效:
- JSON字符串语法错误:原代码中
string json = @""的写法错误,多行字符串应该直接用@"..."包裹,不需要额外的空引号。 - Dynamic跨环境访问问题:将
JArray转成List<dynamic>后,每个元素实际是JObject,在V8引擎中通过p.age访问属性时,无法正确映射到JObject的属性,导致筛选条件失效。 - JS中实例化C#委托的兼容性问题:在V8里直接
new Pred(p => p.age >25)的方式,无法正确将JS函数转换为C#的Func<dynamic, bool>委托,导致Linq的Where方法无法正确执行。
修正方案一:使用强类型实体类(推荐)
创建强类型的Person类,避免dynamic带来的跨环境访问问题:
public class Person { public int id { get; set; } public string name { get; set; } public int age { get; set; } } public IActionResult Index() { using (var engine = new V8ScriptEngine()) { // 修复JSON字符串语法 string json = @" [ { ""id"": 1, ""name"": ""John"" , ""age"": 25 }, { ""id"": 2, ""name"": ""Jane"" , ""age"": 30 } ]"; var jsonArray = JArray.Parse(json); // 转成强类型列表 var personList = jsonArray.ToObject<List<Person>>(); engine.Script.PersonList = personList; engine.AddHostType(typeof(Enumerable)); engine.AddHostType("Pred", typeof(Func<Person, bool>)); // 此时JS中可以正确访问Person的属性 engine.Execute(@"var result = PersonList.Where(new Pred(p => p.age > 25)).ToList();"); List<Person> filteredList = engine.Script.result; foreach (var person in filteredList) { Console.WriteLine($"Id: {person.id}, Name: {person.name}, Age: {person.age}"); } } return View(); }
修正方案二:在C#端处理Linq筛选(更简单)
如果不需要在V8引擎中执行筛选逻辑,可以直接在C#端完成筛选,避免跨环境的委托问题:
public IActionResult Index() { using (var engine = new V8ScriptEngine()) { string json = @" [ { ""id"": 1, ""name"": ""John"" , ""age"": 25 }, { ""id"": 2, ""name"": ""Jane"" , ""age"": 30 } ]"; var jsonArray = JArray.Parse(json); var personList = jsonArray.ToObject<List<dynamic>>(); // 直接在C#端执行Linq筛选 var filteredList = personList.Where(p => p.age > 25).ToList(); foreach (var person in filteredList) { Console.WriteLine($"Id: {person.id}, Name: {person.name}, Age: {person.age}"); } // 如果需要将结果传入V8引擎 engine.Script.FilteredList = filteredList; } return View(); }
修正方案三:调整V8中委托的使用方式
如果必须在V8中执行Linq,可以通过C#方法包装筛选逻辑,再传入引擎:
public IActionResult Index() { using (var engine = new V8ScriptEngine()) { string json = @" [ { ""id"": 1, ""name"": ""John"" , ""age"": 25 }, { ""id"": 2, ""name"": ""Jane"" , ""age"": 30 } ]"; var jsonArray = JArray.Parse(json); var personList = jsonArray.ToObject<List<dynamic>>(); engine.Script.PersonList = personList; engine.AddHostType(typeof(Enumerable)); // 定义C#筛选方法,传入引擎 engine.Script.FilterAgeGreaterThan = new Func<dynamic, bool>(p => p.age > 25); // 在JS中直接使用该方法作为Where的参数 engine.Execute(@"var result = PersonList.Where(FilterAgeGreaterThan).ToList();"); List<dynamic> filteredList = engine.Script.result; foreach (var person in filteredList) { Console.WriteLine($"Id: {person.id}, Name: {person.name}, Age: {person.age}"); } } return View(); }
以上三种方案都能实现你期望的输出:Id: 2, Name: Jane, Age: 30
内容的提问来源于stack exchange,提问作者user22036353
相关产品推荐
相关产品推荐

