76

In C#, I have successfully serialized an anonymous object into JSON by use of code like this...

var obj = new { Amount = 108, Message = "Hello" };
JavaScriptSerializer serializer = new JavaScriptSerializer();
String output = serializer.Serialize(obj);

However, what I would like to be able to do later is to deserialize the JSON string back into an anonymous object. Something like this...

var obj2 = serializer.Deserialize(output, object);

But the serializer.Deserialize() method requires a second parameter that is the type of object it will deserialize to.

I tried this...

var obj2 = serializer.Deserialize(output, obj.GetType());

But this produces an error:

No parameterless constructor defined for type of '<>f__AnonymousType0`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.

I'm not sure what this error means.

Shamim Hafiz - MSFT
  • 21,454
  • 43
  • 116
  • 176
jdavis
  • 8,255
  • 14
  • 54
  • 62
  • Related posts - [Deserialize JSON into C# dynamic object?](https://stackoverflow.com/q/3142495/465053) & [Deserializing json to anonymous object in c#](https://stackoverflow.com/q/6671972/465053) – RBT Jan 09 '22 at 15:31
  • This has exactly what you're looking for: https://stackoverflow.com/a/70026040/8644294 – Ash K Dec 22 '22 at 15:58

8 Answers8

53

how about dynamics, the fastest way I see is this:

dynamic myObject = JsonConvert.DeserializeObject<dynamic>(output);

decimal Amount = Convert.ToDecimal(myObject.Amount);
string Message = myObject.Message;

Note: You will need Newtonsoft.json.dll reference

i31nGo
  • 1,422
  • 15
  • 11
38

JSON.Net is a powerful library to work with JSON in .Net

There's a method DeserializeAnonymousType you can tap in to.

Update: Json.Net is now included with ASP.Net, however my latest favorite that I use is JsonFX. It's got great linq support as well, check it out.

Update 2: I've moved on from JsonFX, and currently use ServiceStack.Text, it's fast!

Amit G
  • 5,165
  • 4
  • 28
  • 29
Vin
  • 6,115
  • 4
  • 41
  • 55
  • Interesting, looks like exactly what the OP's looking for. – Davy8 Aug 01 '11 at 22:10
  • 1
    Update nov 11, Link is now broken – Kieren Johnstone Nov 11 '12 at 12:13
  • 5
    ServiceStack is not free! For me this was important. I only found out when I reached the limits of the free version. – JDC Apr 30 '15 at 12:21
  • ServiceStack since 4.0.26 is now free, and it supports deserialization to generic `JsonObject`s – thomasb Nov 24 '17 at 12:31
  • 1
    @thomasb I have no idea where you're seeing that... the license for the NuGet package, at least, has a "restricted free usage" clause (version 5.2.0). – Marcel Popescu Sep 14 '18 at 07:11
  • I also wasted time checking ServiceStack on the mention of @thomasb that is free, but it's not true. As of today, [their website](https://servicestack.net/download#free-quotas) reports `Whilst ServiceStack v4+ is a commercially-supported product, we allow free usage of our Commercial Products in small projects and for evaluation purposes`. It's still limited until granted a "free" license, which is unclear how to get, probably upon explicit request and evaluation of the project. – alelom Mar 25 '23 at 09:06
  • There is a free version for individuals and open source projects: https://servicestack.net/free ; I'm not sure what the status was 6 years and 2 main versions ago. Anyway, while still not as fast as ServiceStack, `System.Text.Json` has seen great performance improvements in the latest .Net Core releases : https://medium.com/@tobias.streng/net-performance-series-2-newtonsoft-vs-system-text-json-2bf43e037db0 – thomasb Mar 27 '23 at 08:00
16

How about using the DeserializeObject method, it does not require a specific type. This also solved a similar SO question. The method deserializes to a Dictionary<string, object> containing name/value pairs.

Update: to clarify the error you get when doing this:

var obj2 = serializer.Deserialize(output, obj.GetType());

Given the type of obj, Deserialize will try to create a new instance of the type using a default constructor. Anonymous types in C# does not have a public parameterless constructor, and thus the operation fails.

Community
  • 1
  • 1
Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131
4

This can also be done using the in-built JavaScriptSerializer, as follows:

object result = new JavaScriptSerializer().DeserializeObject(JSONData);

This will return an object[] instance, with Key-Value pairs.

XtraSimplicity
  • 5,704
  • 1
  • 28
  • 28
2

if you use Newtonsoft.Json you can try DeserializeAnonymousType method

    var obj1 = new { Amount = 108, Message = "Hello" };
    var json=JsonConvert.SerializeObject(obj1);

    // or as well
    var json= "{ \"Amount\" : 108, \"Message\" : \"Hello\" }";
   
   //Deserialization

   var definition = new { Amount = 0, Message = "" };

    //obj2 type is "anonymous"
   var obj2 = JsonConvert.DeserializeAnonymousType(json,definition); 

result

{ Amount = 108, Message = "Hello" }
Serge
  • 40,935
  • 4
  • 18
  • 45
1

Recently I have been using the awesome JsonFx.Net library and I've come to appreciate what it does. You can use Nuget Package Manager to install it right inside Visual Studio.

The code goes like this,

var reader = new JsonReader();
string input = @"{ ""first"": ""Foo"", ""last"": ""Bar"" }";
var template = new { first=String.Empty, middle=String.Empty, last=String.Empty };
var output = reader.Read(input, template);

As you can see you can even specify the template for Anonymous Type.

Vin
  • 6,115
  • 4
  • 41
  • 55
1

You can use JObject instead to deserialize the JSON string:

using Newtonsoft.Json.Linq;

string output = "{\"Amount\" = 108, \"Message\" = \"Hello\"}";
var amount = JObject.Parse(output)["Amount"];
RBT
  • 24,161
  • 21
  • 159
  • 240
1

If you do not want to manually provide the type i found the easyest way is just:

var jsonString = JsonHelper.SerializeObject(item);
ExpandoObject obj = JsonHelper.DeserializeObject<ExpandoObject>(jsonString);
Jeroen79
  • 11
  • 1