InteropTests.SystemTextJson.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using System.Reflection;
  2. using System.Text.Json.Nodes;
  3. using Jint.Runtime.Interop;
  4. namespace Jint.Tests.PublicInterface;
  5. public partial class InteropTests
  6. {
  7. [Fact]
  8. public void AccessingJsonNodeShouldWork()
  9. {
  10. const string Json = """
  11. {
  12. "employees": {
  13. "type": "array",
  14. "value": [
  15. {
  16. "firstName": "John",
  17. "lastName": "Doe"
  18. },
  19. {
  20. "firstName": "Jane",
  21. "lastName": "Doe"
  22. }
  23. ]
  24. }
  25. }
  26. """;
  27. var variables = JsonNode.Parse(Json);
  28. var engine = new Engine(options =>
  29. {
  30. // make JsonArray behave like JS array
  31. options.Interop.WrapObjectHandler = static (e, target, type) =>
  32. {
  33. var wrapped = new ObjectWrapper(e, target);
  34. if (target is JsonArray)
  35. {
  36. wrapped.Prototype = e.Intrinsics.Array.PrototypeObject;
  37. }
  38. return wrapped;
  39. };
  40. // we cannot access this[string] with anything else than JsonObject, otherwise itw will throw
  41. options.Interop.TypeResolver = new TypeResolver
  42. {
  43. MemberFilter = static info =>
  44. {
  45. if (info.ReflectedType != typeof(JsonObject) && info.Name == "Item" && info is PropertyInfo p)
  46. {
  47. var parameters = p.GetIndexParameters();
  48. return parameters.Length != 1 || parameters[0].ParameterType != typeof(string);
  49. }
  50. return true;
  51. }
  52. };
  53. });
  54. engine
  55. .SetValue("variables", variables)
  56. .Execute("""
  57. function populateFullName() {
  58. return variables['employees'].value.map(item => {
  59. var newItem =
  60. {
  61. "firstName": item.firstName,
  62. "lastName": item.lastName,
  63. "fullName": item.firstName + ' ' + item.lastName
  64. };
  65. return newItem;
  66. });
  67. }
  68. """);
  69. // reading data
  70. var result = engine.Evaluate("populateFullName()").AsArray();
  71. Assert.Equal((uint) 2, result.Length);
  72. Assert.Equal("John Doe", result[0].AsObject()["fullName"]);
  73. Assert.Equal("Jane Doe", result[1].AsObject()["fullName"]);
  74. // mutating data via JS
  75. engine.Evaluate("variables.employees.type = 'array2'");
  76. engine.Evaluate("variables.employees.value[0].firstName = 'Jake'");
  77. Assert.Equal("array2", engine.Evaluate("variables['employees']['type']").ToString());
  78. result = engine.Evaluate("populateFullName()").AsArray();
  79. Assert.Equal((uint) 2, result.Length);
  80. Assert.Equal("Jake Doe", result[0].AsObject()["fullName"]);
  81. // mutating original object that is wrapped inside the engine
  82. variables["employees"]["type"] = "array";
  83. variables["employees"]["value"][0]["firstName"] = "John";
  84. Assert.Equal("array", engine.Evaluate("variables['employees']['type']").ToString());
  85. result = engine.Evaluate("populateFullName()").AsArray();
  86. Assert.Equal((uint) 2, result.Length);
  87. Assert.Equal("John Doe", result[0].AsObject()["fullName"]);
  88. }
  89. }