497

Is it possible to return a dynamic object from a json deserialization using json.net? I would like to do something like this:

dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);
Syscall
  • 19,327
  • 10
  • 37
  • 52
ryudice
  • 36,476
  • 32
  • 115
  • 163
  • 3
    Consider to generate C# class from JSON http://json2csharp.com/ and use generated class instead of dynamic – Michael Freidgeim Jul 14 '16 at 03:01
  • 2
    Possible duplicate of [Deserialize JSON into C# dynamic object?](http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object) – meJustAndrew Aug 19 '16 at 11:35
  • How do you suggest stackOverflow close a question as "too old"? It's been six years, there are valid answers and reasonable suggestions for every version of .net since then... so many that they aren't really helpful any more. – andrew lorien Feb 27 '17 at 02:07
  • Does this help? https://stackoverflow.com/a/70026040/8644294 – Ash K Dec 22 '22 at 15:54

8 Answers8

615

Json.NET allows us to do this:

dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");

Console.WriteLine(d.number);
Console.WriteLine(d.str);
Console.WriteLine(d.array.Count);

Output:

 1000
 string
 6

Documentation here: LINQ to JSON with Json.NET

See also JObject.Parse and JArray.Parse

David
  • 4,665
  • 4
  • 34
  • 60
Michael Pakhantsov
  • 24,855
  • 6
  • 60
  • 59
  • 42
    Note that for arrays the syntax is `JArray.Parse`. – jgillich May 15 '14 at 10:24
  • 7
    Why do we need to use dynamic word ? i am scared never used before :D – Furkan Gözükara Aug 28 '14 at 00:29
  • 4
    In VB.Net you need to do `Dim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")` – ilans Dec 31 '14 at 16:39
  • 3
    @MonsterMMORPG You should be :) Dynamic is an anti pattern in almost every circumstances, but, every now and then, you may have a situation where it's reasonable to use it. – Pluc Mar 18 '16 at 18:30
  • 4
    With Newtonsoft.Json 8.0.3 (.NET 4.5.2): Microsoft.CSharp.RuntimeBinder.RuntimeBinderException occurred HResult=-2146233088 Message='Newtonsoft.Json.Linq.JObject' does not contain a definition for 'number' Source=Microsoft.CSharp StackTrace: at Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError(CError pError) – user4698855 May 04 '16 at 11:17
  • 2
    Doesn't seem to work in version 10.0.1. You get the runtime binder exception. Answer is false. – Paul K Jul 28 '17 at 17:11
  • Note: you should add the reference Microsoft.CSharp.dll to make use of d.number etc.. – Brampage Nov 13 '17 at 10:14
  • 3
    This is not/no longer (?) returning `dynamic` but a `JObject` instead (`public static JObject Parse(string json, JsonLoadSettings settings);`). Docs here: https://www.newtonsoft.com/json/help/html/LINQtoJSON.htm – Krumelur Oct 16 '18 at 15:14
  • 1
    @Krumelur You can still declare the type as dynamic and then access using property notation as opposed to having to access everything via indexers. The answer is correct. – Robb Vandaveer Mar 25 '19 at 18:29
  • 10 years later, it's still the best answer. – javdromero Apr 21 '22 at 18:55
118

As of Json.NET 4.0 Release 1, there is native dynamic support:

[Test]
public void DynamicDeserialization()
{
    dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
    jsonResponse.Works = true;
    Console.WriteLine(jsonResponse.message); // Hi
    Console.WriteLine(jsonResponse.Works); // True
    Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
    Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
    Assert.That(jsonResponse, Is.TypeOf<JObject>());
}

And, of course, the best way to get the current version is via NuGet.

Updated (11/12/2014) to address comments:

This works perfectly fine. If you inspect the type in the debugger you will see that the value is, in fact, dynamic. The underlying type is a JObject. If you want to control the type (like specifying ExpandoObject, then do so.

enter image description here

David Peden
  • 17,596
  • 6
  • 52
  • 72
  • 23
    This never seems to work. It only returns a JObject, not a dynamic variable. – Paul Sep 09 '14 at 17:52
  • 16
    BTW, this works: JsonConvert.DeserializeObject(STRING); with proper deserialization, so we do not have JObject etc. – Gutek Nov 12 '14 at 15:24
  • 2
    @Gutek not sure what your issue is. Did you run the code? I added asserts to the test and added a property not in the original json. Screenshot of the debugger included. – David Peden Nov 12 '14 at 16:19
  • 1
    @DavidPeden if you have JObject and you will try to bind that in Razor you will get exceptions. Question was about deserializing to dynamic object - JObject is dynamic but contains "own" types like JValue not primitive types. I can't use `@Model.Prop` name in Razor if return type is JValue. – Gutek Nov 17 '14 at 12:32
  • 2
    This works, but each dynamic property is a `JValue`. Which confused me because I was working in the debugger/immediate window and wasn't seeing just `string`s. David shows this in the bottom screenshot. The `JValue` is convertible so you can just do `string m = jsonResponse.message` – Luke Puplett Feb 07 '15 at 11:06
  • Exactly what I was looking for, works fine for me, many thanks! – Sirar Salih Apr 19 '18 at 13:02
  • @Gutek 7 years ago, but still its the answer, thank you :) – Alexandr May 03 '20 at 17:38
  • @Alexandr ah, if only you had waited 3 more days to comment... – David Peden May 03 '20 at 21:16
83

If you just deserialize to dynamic you will get a JObject back. You can get what you want by using an ExpandoObject.

var converter = new ExpandoObjectConverter();    
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);
Joshua Peterson
  • 1,026
  • 7
  • 8
48

I know this is old post but JsonConvert actually has a different method so it would be

var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);
epitka
  • 17,275
  • 20
  • 88
  • 141
  • 27
    That would be deserializing a json payload into an anonymous type, not a dynamic type. Anonymous types and dynamic types are different things, and I don't believe this addresses the question asked. – jrista Aug 01 '12 at 19:12
  • 1
    Is it necessary to use two variables? Why not reuse the first one in the second statement? – RenniePet Jul 23 '13 at 01:06
39

Yes you can do it using the JsonConvert.DeserializeObject. To do that, just simple do:

dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);
Matthew Lock
  • 13,144
  • 12
  • 92
  • 130
oteal
  • 614
  • 2
  • 13
  • 25
  • 2
    `JsonConvert` doesn't contain a method called `Deserialize`. – Can Poyrazoğlu Nov 28 '15 at 17:04
  • 1
    it should just be DeserializeObject, but this should be the accepted answer IMO – superjugy Dec 21 '15 at 16:19
  • 1
    This works :D Thank you very much, all the other answers didn't work for me. I was trying to use DeserializeObject, however instead of jsonResponse["message"] I was using the syntax I normally use with regular class objects: jsonResponse.message – Sasino Dec 28 '20 at 23:05
23

Note: At the time I answered this question in 2010, there was no way to deserialize without some sort of type, this allowed you to deserialize without having go define the actual class and allowed an anonymous class to be used to do the deserialization.


You need to have some sort of type to deserialize to. You could do something along the lines of:

var product = new { Name = "", Price = 0 };
dynamic jsonResponse = JsonConvert.Deserialize(json, product.GetType());

My answer is based on a solution for .NET 4.0's build in JSON serializer. Link to deserialize to anonymous types is here:

http://blogs.msdn.com/b/alexghi/archive/2008/12/22/using-anonymous-types-to-deserialize-json-data.aspx

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Phill
  • 18,398
  • 7
  • 62
  • 102
  • I am with you phill don't know why people down-voting this, if any one can you please.. please explain why ? – PEO Jun 23 '16 at 21:27
  • 20
    They are downvoting because the question is about deserializing without a type. – richard Aug 02 '16 at 04:10
  • 4
    Answer was valid at the time of writing it in 2010 when there was no other solution. It was even the accepted answer for a small period of time until support came in JSON.NET. – Phill Mar 06 '17 at 07:25
  • 1
    This doesn't produce a dynamic object. This produces a JObject which you reference as a dynamic. But its still a JObject inside. – ghostbust555 Jan 17 '18 at 19:10
  • 1
    @ghostbust555 so, no different to `dynamic d = JObject.Parse...` – Phill Oct 06 '20 at 06:24
7

If you use JSON.NET with old version which didn't JObject.

This is another simple way to make a dynamic object from JSON: https://github.com/chsword/jdynamic

NuGet Install

PM> Install-Package JDynamic

Support using string index to access member like:

dynamic json = new JDynamic("{a:{a:1}}");
Assert.AreEqual(1, json["a"]["a"]);

Test Case

And you can use this util as following :

Get the value directly

dynamic json = new JDynamic("1");

//json.Value

2.Get the member in the json object

dynamic json = new JDynamic("{a:'abc'}");
//json.a is a string "abc"

dynamic json = new JDynamic("{a:3.1416}");
//json.a is 3.1416m

dynamic json = new JDynamic("{a:1}");
//json.a is integer: 1

3.IEnumerable

dynamic json = new JDynamic("[1,2,3]");
/json.Length/json.Count is 3
//And you can use json[0]/ json[2] to get the elements

dynamic json = new JDynamic("{a:[1,2,3]}");
//json.a.Length /json.a.Count is 3.
//And you can use  json.a[0]/ json.a[2] to get the elements

dynamic json = new JDynamic("[{b:1},{c:1}]");
//json.Length/json.Count is 2.
//And you can use the  json[0].b/json[1].c to get the num.

Other

dynamic json = new JDynamic("{a:{a:1} }");

//json.a.a is 1.
ranieuwe
  • 2,268
  • 1
  • 24
  • 30
chsword
  • 2,032
  • 17
  • 24
7

Yes it is possible. I have been doing that all the while.

dynamic Obj = JsonConvert.DeserializeObject(<your json string>);

It is a bit trickier for non native type. Suppose inside your Obj, there is a ClassA, and ClassB objects. They are all converted to JObject. What you need to do is:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
s k
  • 4,342
  • 3
  • 42
  • 61