Reputation: 13690
I am using the Newtonsoft JSON library to perform dynamic deserialisation on incoming raw JSON and have found something that I just can't explain.
The starting point is the following JSON string:
{
"task": {
"dueDate": "2012-12-03T00:00:00"
}
}
Nothing too complex there...
In code I am then doing this:
var dyn = JsonConvert.DeserializeObject<dynamic>(rawJson);
DateTime dueDate = dyn.task.dueDate.Value;
This code has been in place for months and works fine, however in a recent test build we were seeing the following error:
'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'task'
Stack Trace: at CallSite.Target(Closure , CallSite , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
Now this is where is gets odd, everything starts to work again if I change the code above from:
DateTime dueDate = dyn.task.dueDate.Value;
to
DateTime dueDate = dyn["task"]["dueDate"].Value;
So, although this is "fixed" I don't understand why this fixes it and what the possible cause could be. Does anybody have any ideas
Upvotes: 44
Views: 75645
Reputation: 2028
I have/had a similar problem as I had a project that was doing a LOT of dynamic stuff.
What I narrowed it down to was..... JsonElement and serialization. Using Dynamic, the underlying type exists, and serialization to JSON what should it serialize that object to? Dynamic could be: a string, numeric,datetime, True, false etc. so they need to put a little meta data down too, so that when you refer to the dynamic, it knows that on serialization
So... when you serialize, the I believe the dynamic gets converted to a JsonElement - specifying a ValueKind, and a Value as properties.
When you de-serialize, things get complicated... JSON to C# will match the property in the class, and if its dynamic as a destination - something needs to restore the dynamic based on the JSON Element information.
This is where things get fuzzy, but I know for sure that if you look into the Serialzation, and you see ValueKind, you are likely to have a problem on the other side.
Also watch the Text.Json (MS) deserialization, and serialization, as I believe their is a difference in how newtonsoft and MS handle the serialization and deserialization of dynamics.
Upvotes: 0
Reputation: 736
I had the same problem with an app using Json.NET. The issue recurred only on one specific machine and it turned out that the machine had another version of Json.NET installed in GAC. After removing it from GAC the app started to work correctly.
Upvotes: 1
Reputation: 11
I had this issue going on for a while, turns out, the DLL used was compiled for .NET 3.5 which did not support dynamic.... Make sure your DLL is compiled for .NET 4.5 and above
Upvotes: 1
Reputation: 1287
You can try this:
dynamic task = JObject.Parse(rawJson);
Documentation: Querying JSON with dynamic
Upvotes: 52
Reputation: 1062
I had the same problem.
Json.NET 6.0.4 cause this issue.You should change it to Json.Net 6.0.5. None of the project should reference to Json.NET 6.0.4 .
Go to Tools -> NuGet Package Manager -> Manage NuGet Packages for solution... and check, if any of the projects use Json.NET 6.0.4, fix them.
Upvotes: 4
Reputation: 8749
In my case it turned out I was catching first chance exceptions, so although this exception was being thrown it was not, in fact, preventing my code from executing.
It would still be nice to know why this happens for some content deserialized by Json.NET, but not all content. For example, I have a dynamic object i serialize with json.net in a unit test, then deserialize the serialized content. The serialized content looks identical to content which, at run time, causes runtime binder exceptions to be thrown.
Upvotes: 5
Reputation: 6146
This is definitely some referencing issue, I just had the same problem, turned out the issue was that I had added the packages folder to the project so that I could check it in in VSS (sorry, mandatory), as soon as I removed the packages folder from visual studio, it started working fine
Upvotes: 2