I have JSON objects having embedded arrays – with no predefined strongly typed class to deserialize to. ExpandoObject deserialization with Json.Net works, but the array is deserialized to list, which is an issue for me. I need expndoobject with arrays. Is there any setting I could use with Json.NET to achieve this?
Example:
var obj = """
{
"name": "John",
"age": 18,
"grid": [
{
"type": "A",
"price": 13
},
{
"type": "B",
"price": 1
},
{
"type": "A",
"price": 17
}
]
}
""";
var engine = new Engine()
.Execute("function eval(value) { return value.grid.filter((it)=>it.type === 'A').map(it=>it.price).reduce((a,b)=>a+b) }");
dynamic v = JsonConvert.DeserializeObject<ExpandoObject>(obj, new ExpandoObjectConverter());
engine.Invoke("eval", v);
Where this library is used: https://github.com/sebastienros/jint
Result:
And I need an array there, or otherwise the call fails ("Property ‘filter’ of object is not a function").
Using dynamic v= Newtonsoft.Json.Linq.JObject.Parse(obj);
I got this:
And still fails with: "Accessed JArray values with invalid key value: "filter". Int32 array index expected."
If I define classes for this sample:
class Inner
{
public string Type { get; set; }
public int Price { get; set; }
}
class X
{
public string Name { get; set; }
public int Age { get; set; }
public Inner[] Grid { get; set; }
}
it is parsed just fine (var v = JsonConvert.DeserializeObject<X>(obj);
) and the code returns what I am expecting. Not so when I use List<Inner>
instead of the array. Hence the problem is that it is not an array.
So I am looking for any solution that results in an array at that position.
3
Answers
I have created a modified version of the original ExpandoObjectConverter. And that works.
Yes, I am aware, that the JS engine part might change, as this is beta. However, my JS function is perfectly valid. I don't really expect the engine to be worse in compatibility with the standards and not better. But my error was not related to that. I simply asked for a solution to deserialize to an array instead of a list.
This is a Jint issue. The latest stable version won’t even parse the JS function. The following code, using the latest stable 2.11.58, throws without any data:
This throws
The latest stable doesn’t understand arrow functions to begin with.
The latest 3.0 beta,
3.0.0-beta-2044
can parse this but throws with a different error than the one in the question. I guess the latest beta has progressed a bit. This timefilter
is recognized but it doesn’t work yet.Invoking the function with data
throws
In this case, Jint tried to use
filter
as an index value forgrid
.Array access does work though, so it’s not JArray that’s causing the problem.
This JS function :
Works and returns
A
why don’t try something like this