44

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

MrEyes
  • 13,059
  • 10
  • 48
  • 68
  • Did you change the version of Json.NET you are using? – Daniel Hilgarth Dec 03 '12 at 13:11
  • Nope, that was my first thought - looking at the change history on both the code and the library shows no changes to what is in (and working) in live – MrEyes Dec 03 '12 at 13:13
  • 4
    Are you sure this is not a "first chance exception" - typical for dynamics (maybe you have increased details level in your error login etc.)? – tpeczek Dec 03 '12 at 13:22
  • A small test with the latest version of Json.NET shows that your code works - so no regression here. – Daniel Hilgarth Dec 03 '12 at 13:34
  • 1
    On further investigation this is some sort of environmental issue, I have taken the libraries onto a dev box and they work fine. So this is an issue with the test environment, maybe .NET versions or something – MrEyes Dec 03 '12 at 15:20

7 Answers7

52

You can try this:

dynamic task = JObject.Parse(rawJson);

Documentation: Querying JSON with dynamic

James Newton-King
  • 48,174
  • 24
  • 109
  • 130
Hylaean
  • 1,237
  • 13
  • 19
  • 11
    Because he is asking to understand why it doesn't work in the example provided, because it *should* work for the example provided. – Shaun Wilson Dec 23 '13 at 09:00
  • 1
    Small issue with it: you have to know if it's an object or an array and use either JObject.Parse() or JArray.Parse(). In other words you need to know if you are deserializing an array or an object on beforehand. dynamic t1 = JObject.Parse(@"[{'a':10}]"); //fail dynamic t2 = JArray.Parse(@"[{'a':10}]"); //pass dynamic t3 = JObject.Parse(@"{'a':10}"); //pass dynamic t4 = JArray.Parse(@"{'a':10}"); //fail – wvd_vegt Mar 31 '18 at 08:41
5

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.

Shaun Wilson
  • 8,727
  • 3
  • 50
  • 48
4

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.

DaNeSh
  • 1,022
  • 1
  • 14
  • 24
  • For the record, same issue with Json.NET 6.0.3. Fixed latest version 7.0.1. – Eric Boumendil Dec 02 '15 at 15:02
  • 2
    As an interesting aside, I downloaded the Newtonsoft.JSON source and did a search on "task". The OPs exact raw JSON is entered in a test method... who knows why this occurred but someone in Newtonsoft has been reading this. Looks like the bottom line is that this is (or was) a bug with the library. – RLH Dec 31 '15 at 14:23
2

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

BlackTigerX
  • 6,006
  • 7
  • 38
  • 48
1

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.

v.shashenko
  • 716
  • 6
  • 11
1

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

E Perl
  • 11
  • 1
  • 1
0

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.

codeputer
  • 1,987
  • 3
  • 19
  • 45