You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC中Microsoft.ClearScript.V8的Linq Where过滤JSON失效求助

问题分析与解决

你的代码存在几个关键问题导致Linq Where无法正常生效:

  1. JSON字符串语法错误:原代码中string json = @""的写法错误,多行字符串应该直接用@"..."包裹,不需要额外的空引号。
  2. Dynamic跨环境访问问题:将JArray转成List<dynamic>后,每个元素实际是JObject,在V8引擎中通过p.age访问属性时,无法正确映射到JObject的属性,导致筛选条件失效。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 18:53:09