microsoft / ClearScript

A library for adding scripting to .NET applications. Supports V8 (Windows, Linux, macOS) and JScript/VBScript (Windows).
https://microsoft.github.io/ClearScript/
MIT License
1.77k stars 148 forks source link

How to use Linq in jsondata in microsoft.clearscript.v8 #553

Closed Ommkwn2001 closed 10 months ago

Ommkwn2001 commented 10 months ago

in this case I am use microsoft.clearscript.v8 in asp .net core mvc this is below homecontroller.cs code

  `        
                public IActionResult Index()
                 {

           using (var engine = new V8ScriptEngine())

           {

            string json = @"
    [
        { ""id"": 1, ""name"": ""John"", ""age"": 25 },
        { ""id"": 2, ""name"": ""Jane"", ""age"": 30 }      
    ]";

            // Parse JSON as JArray
            var jsonArray = JArray.Parse(json);

            // Use ClearScript to filter the data
            engine.Script.PersonList = jsonArray.ToObject<List<dynamic>>();
            engine.AddHostType(typeof(Enumerable));
            engine.AddHostType("Pred", typeof(Func<dynamic, bool>));

            engine.Execute(@"
            var result = PersonList.Where(new Pred(p => p.age > 25)).ToList();
        ");

            // Retrieve the result from the script engine
            List<dynamic> filteredList = engine.Script.result;

            // Print filtered results
            foreach (var person in filteredList)
            {
                Console.WriteLine($"Id: {person.id}, Name: {person.name}, Age: {person.age}");
            }
        }
     return view();
    }

`

ClearScriptLib commented 10 months ago

Hello @Ommkwn2001,

Consider this line in your code:

var result = PersonList.Where(new Pred(p => p.age > 25)).ToList();

The expression p.age returns a JValue instance, which isn't comparable to a number in JavaScript. The age comparison always evaluates to false.

The same comparison works in C# because JValue implements special support for dynamic. Unfortunately, V8 doesn't allow the host to overload JavaScript's comparison operators.

One way to make it work is by explicitly invoking the Value property:

var result = PersonList.Where(new Pred(p => p.age.Value > 25)).ToList();

Another possibility is to use an extension method to implement valueOf for JValue:

public static class JValueExtensions {
    public static object valueOf(this JValue value) => value.Value;
}

And then:

engine.AddHostType(typeof(JValueExtensions));
engine.Execute(@"
    var result = PersonList.Where(new Pred(p => p.age > 25)).ToList();
");

Good luck!

Ommkwn2001 commented 10 months ago

in this case I am use microsoft.clearscript.v8 in asp .net core mvc this is below homecontroller.cs code, when i debug the code the resultJson = [] and the filteredProducts's count = 0, so how to field name change and get new json with changes

      `          using (var engine = new V8ScriptEngine())
           {

            string additionalJson = @"
                            {
                                ""Account"": {
                                    ""AccountName"": ""Firefly"",
                                    ""Order"": [
                                        {
                                            ""OrderID"": ""order103"",
                                            ""Product"": [
                                                {
                                                    ""ProductName"": ""Bowler Hat"",
                                                    ""ProductID"": 858383,
                                                    ""Price"": 34.45,
                                                    ""Quantity"": 2
                                                },
                                                {
                                                    ""ProductName"": ""Trilby hat"",
                                                    ""ProductID"": 858236,
                                                    ""SKU"": ""0406634348"",
                                                    ""Price"": 21.67,
                                                    ""Quantity"": 1
                                                }
                                            ]
                                        },
                                        {
                                            ""OrderID"": ""order104"",
                                            ""Product"": [
                                                {
                                                    ""ProductName"": ""Bowler Hat"",
                                                    ""ProductID"": 858383,
                                                    ""SKU"": ""040657863"",
                                                    ""Price"": 34.45,
                                                    ""Quantity"": 4
                                                },
                                                {
                                                    ""ProductID"": 345664,
                                                    ""SKU"": ""0406654603"",
                                                    ""ProductName"": ""Cloak"",
                                                    ""Price"": 107.99,
                                                    ""Quantity"": 1
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }";

            // Parse JSON as JObject
            var jsonObject = JObject.Parse(additionalJson);

            // Use ClearScript to filter the data
            engine.Script.ProductList = jsonObject["Account"]["Order"]
                .SelectMany(order => order["Product"].ToObject<List<dynamic>>())
                .ToList();

            engine.AddHostType(typeof(Enumerable));
            engine.AddHostType("Pred", typeof(Func<dynamic, bool>));

            engine.Execute(@"
   var result = [];
    for (var i = 0; i < ProductList.length; i++) {
    var product = ProductList[i];
     result.push({ ProductN: product.ProductName });
   }
     var resultJson = JSON.stringify(result);
     resultJson;
       ");

                string resultJson = engine.Evaluate("resultJson") as string;

            // Check if the resultJson is not null or empty
            if (!string.IsNullOrEmpty(resultJson))
            {
                // Deserialize the JSON into a list
                List<dynamic> filteredProducts = JsonConvert.DeserializeObject<List<dynamic>>(resultJson);

                // Print filtered results
                foreach (var product in filteredProducts)
                {
                    Console.WriteLine($"ProductN: {product.ProductN}");
                }
            }
            else
            {
                Console.WriteLine("No data found in resultJson.");
                       }     
`
ClearScriptLib commented 10 months ago

Regarding this JavaScript code:

for (var i = 0; i < ProductList.length; i++) {
    var product = ProductList[i];
    result.push({ ProductN: product.ProductName });
}

Since ProductList is a .NET list, it has no length property. Try Count instead.

Cheers!

ClearScriptLib commented 10 months ago

Please reopen this issue if you have additional questions or comments about this topic. Thank you!