Deserialize JSON object into dynamic object using Json.net
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
Deserialize JSON into C# dynamic object?
If you are happy to have a dependency upon the System.Web.Helpers
assembly, then you can use the Json
class:
dynamic data = Json.Decode(json);
It is included with the MVC framework as an additional download to the .NET 4 framework. Be sure to give Vlad an upvote if that's helpful! However if you cannot assume the client environment includes this DLL, then read on.
An alternative deserialisation approach is suggested here. I modified the code slightly to fix a bug and suit my coding style. All you need is this code and a reference to System.Web.Extensions
from your project:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
public sealed class DynamicJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
}
#region Nested type: DynamicJsonObject
private sealed class DynamicJsonObject : DynamicObject
{
private readonly IDictionary<string, object> _dictionary;
public DynamicJsonObject(IDictionary<string, object> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
}
public override string ToString()
{
var sb = new StringBuilder("{");
ToString(sb);
return sb.ToString();
}
private void ToString(StringBuilder sb)
{
var firstInDictionary = true;
foreach (var pair in _dictionary)
{
if (!firstInDictionary)
sb.Append(",");
firstInDictionary = false;
var value = pair.Value;
var name = pair.Key;
if (value is string)
{
sb.AppendFormat("{0}:\"{1}\"", name, value);
}
else if (value is IDictionary<string, object>)
{
new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
}
else if (value is ArrayList)
{
sb.Append(name + ":[");
var firstInArray = true;
foreach (var arrayValue in (ArrayList)value)
{
if (!firstInArray)
sb.Append(",");
firstInArray = false;
if (arrayValue is IDictionary<string, object>)
new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
else if (arrayValue is string)
sb.AppendFormat("\"{0}\"", arrayValue);
else
sb.AppendFormat("{0}", arrayValue);
}
sb.Append("]");
}
else
{
sb.AppendFormat("{0}:{1}", name, value);
}
}
sb.Append("}");
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!_dictionary.TryGetValue(binder.Name, out result))
{
// return null to avoid exception. caller can check for null this way...
result = null;
return true;
}
result = WrapResultObject(result);
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
if (indexes.Length == 1 && indexes[0] != null)
{
if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
{
// return null to avoid exception. caller can check for null this way...
result = null;
return true;
}
result = WrapResultObject(result);
return true;
}
return base.TryGetIndex(binder, indexes, out result);
}
private static object WrapResultObject(object result)
{
var dictionary = result as IDictionary<string, object>;
if (dictionary != null)
return new DynamicJsonObject(dictionary);
var arrayList = result as ArrayList;
if (arrayList != null && arrayList.Count > 0)
{
return arrayList[0] is IDictionary<string, object>
? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)))
: new List<object>(arrayList.Cast<object>());
}
return result;
}
}
#endregion
}
You can use it like this:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
So, given a JSON string:
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
The following code will work at runtime:
dynamic data = serializer.Deserialize(json, typeof(object));
data.Date; // "21/11/2010"
data.Items.Count; // 2
data.Items[0].Name; // "Apple"
data.Items[0].Price; // 12.3 (as a decimal)
data.Items[1].Name; // "Grape"
data.Items[1].Price; // 3.21 (as a decimal)
Is it possible to deserialize json string into dynamic object using System.Text.Json?
tl:dr JsonNode is the recommended way but dynamic typing with deserializing to ExpandoObject works and I am not sure why.
It is not possible to deserialize to dynamic in the way you want to. JsonSerializer.Deserialize<T>()
casts the result of parsing to T
. Casting something to dynamic
is similar to casting to object
Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time
docs.
The following code snippet shows this happening with your example.
var jsonString = "{\"foo\": \"bar\"}";
dynamic data = JsonSerializer.Deserialize<dynamic>(jsonString);
Console.WriteLine(data.GetType());
Outputs: System.Text.Json.JsonElement
The recommended approach is to use the new JsonNode which has easy methods for getting values. It works like this:
JsonNode data2 = JsonSerializer.Deserialize<JsonNode>(jsonString);
Console.WriteLine(data2["foo"].GetValue<string>());
And finally trying out this worked for me and gives you want you want but I am struggling to find documentation on why it works because according to this issue it should not be supported but this works for me. My System.Text.Json package is version 4.7.2
dynamic data = JsonSerializer.Deserialize<ExpandoObject>(jsonString);
Console.WriteLine(data.GetType());
Console.WriteLine(data.foo);
Deserialize Dynamic JSON Object
Using @Liam's suggestion of JObject I have come up with this working solution
public class MyObject
{
public int id { get; set; }
public int qty { get; set; }
public string discount { get; set; }
public decimal price { get; set; }
}
and then after retrieving the JSON response...
var jsonObj = JsonConvert.DeserializeObject<JObject>(response);
List<MyObject> myObjects = new List<MyObject>();
foreach (var item in jsonObj.AsJEnumerable())
{
var csp = JsonConvert.DeserializeObject<List<MyObject>>(item.First.ToString());
csp.ForEach(a => { a.product_id = Convert.ToInt32(item.Path); });
myObjects.AddRange(csp);
}
convert json response to dynamic specific object in .net C#
You can try to use JsonConvert.DeserializeObject
to convert tem1 to Object
.
string tem1 = "{\n \"lmsUserId\": 10268,\n \"landlordProfileId\": \"2ea81674-6ca6-478c-a9c6-fefbe9572f28\",\n \"firstName\": \"Testbusiness\",\n \"lastName\": \"business\",\n \"email\": \"yesteluydi@vusra.com\",\n \"createdBy\": 1551,\n \"createdDate\": \"2022-05-05T17:05:10.37\",\n \"user\": null,\n \"linkedLLCs\": null,\n \"ssn\": null,\n \"accountTypeId\": 2,\n \"completeLater\": false\n}";
var s = JsonConvert.DeserializeObject<Object>(tem1);
result:
json deserialization to C# with dynamic keys
If you are using Json.NET, you can use JsonConvert.DeserializeObject<Dictionary<string, Dataset>>(json)
and the keys of the dictionary will be nasdaq_imbalance
, DXOpen IM
, Float Shares
Deserialize JSON to a dynamic object or a class in C#
You can just do:
var test = new EValues {
values = JsonConvert.DeserializeObject<dynamic>(serializedObject)
};
The JSON that would correspond to EValues
would have an extra level of nesting { "values" : {} }
not present in your serializedObject
JSON.
Related Topics
Parsing CSV Files in C#, With Header
C# Compiler Error: "Not All Code Paths Return a Value"
How to Create a Dropdownlist from an Enum in ASP.NET MVC
What Does the =≫ Operator Mean in a Property
Can't Operator == Be Applied to Generic Types in C#
Cleanest Way to Write Retry Logic
Memory Leak Using Streamreader and Xmlserializer
How to Enable Cors in ASP.NET Core
Copy the Entire Contents of a Directory in C#
How Would I Run an Async Task≪T≫ Method Synchronously
Encrypting & Decrypting a String in C#
Filtering on Include in Ef Core
Given a Datetime Object, How to Get an Iso 8601 Date in String Format
How to Register Multiple Implementations of the Same Interface in ASP.NET Core