Turn a JSON string into a dynamic object - c#

I'm trying to create a dynamic object from a JSON string in C#. But i can't get it done.
Normally i would get a JSON string through a web service call but in this case I simply created a simple class which I turn into a JSON string. Then I try to turn it back into a dynamic object with the exact same structure as if it was an instance of the Entity class. But that's where I'm having trouble.
This is the class that i turn into a JSON string:
public class Entity
{
public String Name = "Wut";
public String[] Scores = {"aaa", "bbb", "ccc"};
}
Then in somewhere in my code i do this:
var ent = new Entity();
// The Serialize returns this:
// "{\"Name\":\"Wut\",\"Scores\":[\"aaa\",\"bbb\",\"ccc\"]}"
var json = new JavaScriptSerializer().Serialize(ent);
dynamic dynamicObject1 = new JavaScriptSerializer().DeserializeObject(json);
dynamic dynamicObject2 = Json.Decode(json);
When I debug this code then i see that the first dynamicObject1 returns a Dictionary. Not really what I'm after.
The second dynamicObject2 looks more like the Entity object. It has a property called Name with a value. It also has a dynamic array called Scores, but for some reason that list turns out to be empty...
Screenshot of empty Scores property in dynamic object:
So I'm not having any luck so far trying to cast a JSON string to a dynamic object. Anyone any idea how I could get this done?

Using Json.Net
dynamic dynamicObject1 = JsonConvert.DeserializeObject(json);
Console.WriteLine(dynamicObject1.Name);

Using Json.Net but deserializing into a ExpandableOBject, a type that is native to C#:
dynamic obj= JsonConvert.DeserializeObject<ExpandoObject>(yourjson);
If the target type is not specified then it will be convert to JObject type instead. Json object has json types attached to every node that can cause problems when converting the object into other dynamic type like mongo bson.

Related

C# Serializing an objects into JSON but retain the name

So I'm trying to serialize a Dictionary:
Dictionary<string, List<MyClass>>
My class contains a property called MyPropery
However the string comes out as "{"List1":[{"MyProperty":[]}]}"
How would I be able to make it convert to {"List1":["MyClass":{"MyProperty":[]}]}
To achieve what you want, you would need something like:
var obj = new Dictionary<string, List<Dictionary<string, MyClass>>>();
As kalimag pointed out, ["attr": "value"] isn't a valid JSON. The serialization of the object obj, illustrated above, could yield something like:
{"List1": [{"MyClass": {"MyProperty": []}}]}
Which is a valid JSON.

asp.net - How to get / deserialize object of JsonPatchDocument?

I could serialize the JsonPatchDocument model by using JsonConvert.SerializeObject(), but the type of result is string, how can I convert it to normal array type? Or how to get JsonPatchDocument object straight to array?
var pathSerialized = JsonConvert.SerializeObject(patch);
Console.WriteLine(pathSerialized);
// Result as string:
// "[{"value":"2018-08-30","path":"/openTo","op":"replace"},{"value":"2018-04-01","path":"/openFrom","op":"replace"}]"
You don't have to serialize the JsonPatchDocument object at all. You can access its properties directly through the object. For example filtering for the path property:
var elementsWithPath = patch.Operations.Where(o => o.path.Equals("some path"));
I think you might be looking to do something with JTokens from the Newtonsoft.Json.Linq namespace. You can turn the pathserialized string into a JToken with var jToken = JToken.Parse(pathSerializer), then explore the underlying objects and properties by enumerating them with var childTokens = jToken.Children().
One of those child tokens is going to be a JObject, which is a Json representation of an object. You can access properties of a JObject with jObject["propertyName"].

NewtonSoft JsonConvert SerializeObject Dictionary of Object Escape Chars

I'm having some trouble using the JsonConvert.SerializeObject method concerning escape chars in WCF. My web method returns a Stream as follows:
return new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(myObject)));
This works fine apart from one of the properties of myObject is a Dictionary of <string, object>. All of the simple types serialize correctly, however when I try and add my custom class as a value I get the type returned instead of the data. On realising this comes from the serialiser calling .ToString on my custom class I've tried overriding it with:
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
However the returned data now includes escape chars
{
"my_dictionary": {
"elem_1": "{\"Prop1\":null,\"Prop2\":3}",
"elem_2": "{\"Prop1\":null,\"Prop2\":3}",
"int_property" : 123
}
}
Any ideas on how I could avoid my custom class being escaped in this way and returned as an array?
Thanks in advance, Matt
I use JavaScriptSerializer (just replace "Object" with your custom class)
using System.Web.Script.Serialization;
List<Object> list = new List<Object>();
JavaScriptSerializer jss = new JavaScriptSerializer();
string res = jss.Serialize(list);
and get this format with "res" value:
[{"IdEmpresa":1,"Nombre":"Test","URL":"http:/localhost:8080/","Activo":true},IdEmpresa":2,"Nombre":"Test2,","URL":"http://localhost:8081/","Activo":true}]
I've realised there was a mistake in the code. The class that was being serialised actually returned a Dictionary the conversion of the object to a string was causing the behaviour I'd observed and in reality the serializer was perfectly able to serialise the objects correctly.

JSON.net unserialize list of different objects

How can i unserialize a list of different objects uwing JSON.net?
string myJson = "[{action: 'a1', target: 4},{action: 'a2', targets: [1,2,3], {action:'a3', text:'targets altered'}}]";
This example presents a list of 3 different objects.
If I unserialize as a basic Object, I cannot access any members (as the base Object class doesn't have them).
I've looked over http://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm but I don't understand if it can help me.
with that method you posted, your json should contain extra info to indicate what type it is,which means you need to modify how the source of json to serialize,and make sure the you use the same class,namespace as the source serialized.
Or,use Object or dynamic as type of target, and to convert it in later use may be easier.
Use the dynamic type.
You can access elements as if they were properties. If a property doesn't exist, the dynamic type will return null instead of throwing an exception
dynamic actions = JsonConvert.DeserializeObject(myJson);
foreach (var action in actions)
{
var name = action.action.ToString();
var target = action.target.ToString();
var text = action.text.ToString();
if (target == null)
{
dynamic targets = action.targets;
}
}

How to receive JSON data into Web API ApiController method?

I'm writing a Web API ApiController with several PUT methods that receive JSON data. The JSON is not deterministic and hence cannot be hard-mapped to a custom C# object, but needs to be received as Dictionaries/Sequences (Maps/Lists).
I have tried using an IDictionary for the data parm of the PUT method in the controller, and this sort of works -- the data appears to be mapped from JSON to the dictionary. However, it's necessary to declare the dictionary as <String,Object>, and there's no clear way to then retrieve the Object values as their appropriate types. (I've found a few suggested kluges in my searching, but they are just that.)
There is also a System.Json.JsonObject type which I finally managed to get loaded via NuGet, but when I use that the system does not appear to know how to map the data.
How is this typically done? How do you implement an ApiController method that receives generic JSON?
I can see three basic approaches:
Somehow make Dictionary/Sequence work with Object or some such.
Make something like System.Json.JsonObject work, perhaps by swizzling the routing info.
Receive the JSON as a byte array and then parse explicitly using one of the C# JSON toolkits available.
(As to how dynamic the data is, JSON objects may have missing entries or extraneous entries, and in some cases a particular entry may be represented as either a single JSON value or a JSON array of values. (Where "value" is JSON array, object, string, number, Boolean, or null.) In general, except for the array/not array ambiguity, the relation between keys and value types is known.)
(But I should note that this is a large project and I'll be receiving JSON strings from several other components by other authors. Being able to examine the received type and assert that it's as expected would be quite useful, and may even be necessary from a security standpoint.)
(I should add that I'm a relative novice with C# -- have only been working with it for about 6 months.)
You've got to know what kind of data you're expecting, but I have had success doing this in the past using dynamic typing.
Something like this:
[Test]
public void JsonTester()
{
string json = "{ 'fruit':'banana', 'color':'yellow' }";
dynamic data = JsonConvert.DeserializeObject(json);
string fruit = data["fruit"];
string color = data["color"];
Assert.That(fruit == "banana");
Assert.That(color == "yellow");
}
Edit:
You either need to know the type you want to deserialize to beforehand - in which case you can deserialize it to that type immediately.
Or you can deserialize it to a dynamic type, and then convert it to your static type once you know what you want to do with it.
using Newtonsoft.Json;
using NUnit.Framework;
public class DTO
{
public string Field1;
public int Field2;
}
public class JsonDeserializationTests
{
[Test]
public void JsonCanBeDeserializedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var data = JsonConvert.DeserializeObject<DTO>(json);
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
[Test]
public void JsonCanBeDeserializedToDynamic_AndConvertedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var dynamicData = JsonConvert.DeserializeObject<dynamic>(json);
var data = new DTO { Field1 = dynamicData["Field1"], Field2 = dynamicData["Field2"] };
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
}

Categories