Generate JSON string from dynamic ExpandoObject - c#

I am using C# and trying to generate a JSON string from a dynamic object.
dynamic reply = new System.Dynamic.ExpandoObject();
reply.name = "John";
reply.wins = 42;
string json = System.Web.Helpers.Json.Encode(reply);
System.Console.WriteLine(json);
(Note, the above requires a reference to the System.Web.Helpers assembly.)
I was hoping for this to output the string:
{"name":"John","wins":42}
But it actually outputs:
[{"Key":"name","Value":"John"},{"Key":"wins","Value":42}]
What do I need to change to get the output I was hoping for?

Just download the Newtonsoft.Json Nuget package.
That's the preferred way of working with json in c#.
Your code using Newtonsoft would be:
dynamic reply = new System.Dynamic.ExpandoObject();
reply.name = "John";
reply.wins = 42;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(reply);
System.Console.WriteLine(json);
EDIT:
I just want to explain better why you're getting that result when you're using the System.Web.Helpers.Json.Encode method.
An ExpandoObject is an object which fields are defined at runtime, different than a regular object which fields/properties/methods .. are defined at compile-time. To be able to define them at run-time the expando object internally holds a dictionary, which is a collection of key-value pairs.
I don't know how that helper works but it's probably just a simple serializer and that's why it's serializing to an array of key- value pairs instead of the actual object you're expecting. The library Newtonsoft.Json is almost an standard for c# projects and obviously is aware of how the Expando Object works internally.

Using the Newtonsoft.Json tools:
using Newtonsoft.Json;
/// skip a bunch of other implementation details.
var json = Newtonsoft.Json.JsonConvert.SerializeObject(reply);
That's how I do it.

Related

Is it possible to deserialize json string into dynamic object using System.Text.Json?

I am using System.Text.Json package to use the serialization and deserialization.
I can deserialize a json string into an object when the type is explicitly specified like below.
var data = JsonSerializer.Deserialize<PersonType>(jsonString);
But the dynamic type does not work. Is it possible to deserialize without having to specify the type? Thank you!
var data = JsonSerializer.Deserialize<dynamic>(jsonString);
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);
I have tried using System.Text.Json in a dynamic way and it just does not work in an easy and meaningful way it seems. So while not a direct answer to your question, but I was "forced" to use the good old Newtonsoft.Json that just works:
dynamic result = JObject.Parse(message);

Extract data from Json with json.net

so I have a JSON text and I need to Extract Value of some fields from it
{"data":{"shortcode":{"id":"id123","shortcode":"alpha1","by":{"page_info":{"has_next_page":true,"cursor":"sometext=="},"edges":[{"node":{"id":"id1234","username":"admin123","full_name":"admin name",}},{"node":{"id":"id4321","username":"user123","full_name":"user ",}}]}}},"status":"ok"}
now I need the value of every single "username" field and "cursor" from it
I'm new to this topic and I appreciate any kind of help
You could install Newtonsoft.Json, as a Nuget package, if you don't already have it installed in your project. Then use JsonConvert.DeserializeObject() method to parse it into a dynamic object type, using which you can access all its fields/properties.
Code would look something like this-
Add referenceto Newtonsoft.Json
using Newtonsoft.Json;
DeserializeObject method to parse a string into dynamic type (dynamic can be used instead of var)
var obj = JsonConvert.DeserializeObject<dynamic>(text);
For cursor field mentioned in your example
Console.WriteLine(obj.data.shortcode.by.page_info.cursor);
Iterate for each username mentioned your example
foreach (var edge in obj.data.shortcode.by.edges)
{
Console.WriteLine(edge.node.id);
}
NOTE- Because you are using a dynamic type, you will have to be sure that you check for null values to avoid any "NullRefereneException".
Well you can make a new class that match the structure of your json then deserialize the json into that class.

C# Creating generic List from JArray

I'm working on a dynamic import proces from Json to object array.
Getting a little bit stuck by creating a List<> based on a string reference to the class object.
I'm importing json data from a REST server and using a business objects list to map the json data to predefined classes that can be configured. I'm using NewtonSoft.Json for the parsing of the data to classes.
string classname = "BusinessObjects.Contact";
Type classtype = Type.GetType(classname);
// ... filled jsonstring from api request
string json = "[]"; // json filled from rest request
JObject obj = JObject.Parse(json);
JArray array = (JArray)obj["contacts"];
// the issue part...
var records = array.ToObject<List<classtype>>();
The compiler states I'm using a variable as a type. Which makes sense, but can't find a way around it.
Any help would be appreciated!
Rather than deserializing your JArray, you could access it dynamically as shown in Querying JSON with dynamic. But if you would prefer to deserialize to a fixed list type, since you are writing non-generic reflection-based code, you can do:
var listType = typeof(List<>).MakeGenericType(classtype);
var records = array.ToObject(listType);
Notes:
Given an open generic type such as List<>, Type.MakeGenericType() creates a closed generic type by substituting the Type argument(s) for the type parameters of the open type.
JToken.ToObject() is a non-generic version of ToObject() that can deserialize to a specified Type.
Once you have created your records list you can cast it to the non-generic IList interface to access collections items.
Sample fiddle with prototype sample JSON and definition for BusinessObjects.Contact.

C# JavascriptSerializer failing with EF object: RecursionLimit exceeded

I wanted a cheap way to clone a database object. My plan was to serialize and then deserialize the object. My code is as follows:
var newHireRequisition =_context.NewHireRequisitions.Single(x => x.newHireRequisitionPk == newHireRequisitionId);
JavaScriptSerializer js = new JavaScriptSerializer();
js.RecursionLimit = 1;
var json = js.Serialize(newHireRequisition);
NewHireRequisition newReq = js.Deserialize<NewHireRequisition>(json);
As you can see, I set recursion level to one to keep from traversing the relationships of the NewHireRequisitions table. I believe that this is a bug in the 'Serialize' function.
When this code runs, I get an exception on the Serialize command. The exception is:
System.ArgumentException: 'RecursionLimit exceeded.'
The datamodel looks like this:
but I only want the one object in the middle (NewHireRequisition), not the related rows.
Any help with this technique would be appreciated, or another way to shallow clone an entity framwork data object.
Thanks to #crashmaster! Looking at the newtonsoft web page, I see that the Json.Net serializer supports LINQ to JSON, while the .net native JavaScriptSerializer does not. That resolved my issue.

Looking to create JSON Serializer/Deserializer Class using C# 2.0

I am using c#.
Now I am looking to create a "JSONHelper" class, which will Serialize and Deserialize the JSON string data. In my current scenario, I am getting below format string from my web-service which returns JSON type.
I have got a method in my C# code which calls a web-service method, which returns the string JSON type data. See below example.
string userDetails = myWebService.GetMember(username, Password, out Result);
so userDetails value is
{"FullName":"Manoj Singh","username":"Manoj","Miles":2220,"TierStatus":"Gold","TierMiles":23230,"MilesExpiry":12223,"ExpiryDate":"31 January 2011","PersonID":232323,"AccessToken":"sfs23232s232","ActiveCardNo":"232323223"}
Now I want to write JSONHelper Class in which there will be methods to Serialize and Deserialize the string type of JSON, and will return the dictionary type of values.
Have you looked at http://json.codeplex.com/ ?
I've used it and find json.net very good. Not sure why you'd want to write your own.
You can use the JavaScriptSerializer class in the System.Web.Script.Serialization namespace:
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
object result = jsonSerializer.DeserializeObject(jsonString);
Assuming your jsonString represents a object this should return a dictionary. But you will need to check the type carefully as there is no guarantee it won't return an IEnumerable for example if you give it a json list.
Better still you can use a strongly type deserialization:
http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer.aspx
If you know the return signature of your web method this is a far better solution.

Categories