MrEyes
MrEyes

Reputation: 13690

Newtonsoft JSON - Dynamic Objects

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

Answers (7)

codeputer
codeputer

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

v.shashenko
v.shashenko

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

E Perl
E Perl

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

Hylaean
Hylaean

Reputation: 1287

You can try this:

dynamic task = JObject.Parse(rawJson);

Documentation: Querying JSON with dynamic

Upvotes: 52

DaNeSh
DaNeSh

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

wilson0x4d
wilson0x4d

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

BlackTigerX
BlackTigerX

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

Related Questions