DataContractJsonSerializer dynamic object deserialization - c#

I would like to go with DataContractJsonSerializer instead of any third party libs like Json.NET I need to deserialize Json stream which can be one of my C# classes, and I dont know which one it is what i want to do is Deserialize json data -> determine type of this object -> do something with deserialized object according to type of this object. Is there anything to do with DataContractJsonSerializer.KnownTypes Property? Im really new to json.

what i want to do is Deserialize json data -> determine type of this object -> do something with deserialized object according to type of this object. Is there anything to do with DataContractJsonSerializer.KnownTypes Property?
Yes, it is related to the known types. Firstly, you need to specify the type you want to de-serialize in the constructor function. Then you can specify the types may be present in may be present in the object graph.
DataContractJsonSerializer Constructor (Type, IEnumerable)
But I still recommend you using the JSON.NET which will be easier than DataContractJsonSerializer, and the performance is even better. In ASP.NET Web API, JSON.NET is the default JSON serializer.

or JavaScriptSerializer
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string, dynamic>>(strRet);
StringBuilder sbErr = new StringBuilder(string.Format("{0} ({1}): {2}", rep.StatusDescription, dict["code"], Environment.NewLine));
if ((dict["errors"] is Dictionary<string, dynamic>)) {
foreach (KeyValuePair<string, dynamic> item in dict["errors"]) {
sbErr.AppendFormat("{0}=", item.Key);
foreach (string item2 in item.Value)
sbErr.AppendFormat("{0}. ", item2);
}
}

Related

Get Tuple from string returned by Tuple.ToString()

Say, we have that code:
var tuple = new Tuple<double, int>(10.6, 2);
var tupleString = tuple.ToString(); //returns "(10.6, 2)";
Can we get a new Tuple instance from tupleString without implementing any custom parsers and JsonConverters and extending TypeConverter?
UPDATE 1
In my production code I have SortedList<Tuple<DayOfWeek, double>, double>. That list is serialized by Json.NET,that converts Dictionary keys by .ToString(). Then JSON is sent to frontend application. Then frontend application send request with that serialized key to server. I have to convert that key to .NET Tuple, but I don't know how to do that.
Of course you can. You can 'simply' parse the output string, but I hope you like writing parsing algorithms then which might get hard, especially when it involves strings and objects...
See for example this one, which is impossible to parse:
var tuple = new Tuple<string, int>("10, 6", 2);
var tupleString = tuple.ToString(); //returns "(10, 6, 2)";
I would suggest to use the items in the tuple itself instead of making a string out of it first:
Tuple<int> tuple2 = tuple.Item2;
If you are serializing it using JSON.NET, you should write or use a custom serializer, like the one mentioned here.
I solved my problem by another way using this answer of Nate Barbettini.
I changed his code to that:
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type type = value.GetType();
IEnumerable keys = (IEnumerable)type.GetProperty("Keys").GetValue(value, null);
IEnumerable values = (IEnumerable)type.GetProperty("Values").GetValue(value, null);
IEnumerator valueEnumerator = values.GetEnumerator();
writer.WriteStartObject();
foreach (object key in keys)
{
valueEnumerator.MoveNext();
writer.WritePropertyName(JsonConvert.SerializeObject(key));
serializer.Serialize(writer, valueEnumerator.Current);
}
writer.WriteEndObject();
}
Then just set custom JsonConverterAttribute to required IDictionary<,> and Json.NET will serialize its keys by JsonConvert.SerializeObject() instead of .ToString(). So that Tuple can be deserialized by Json.NET correctly.

How to convert the following JSON array into IDictionary<string, object>?

Following is the serialized JSON array I want to convert to IDictionary
[
{
"8475": 25532
},
{
"243": 521
},
{
"3778": 15891
},
{
"3733": 15713
}
]
When I tried to use
JsonConvert.DeserializeObject<IDictionary<string, object>>((string)jarray);
I got an error saying:
Cannot cast 'jarray' (which has an actual type of 'Newtonsoft.Json.Linq.JArray') to 'string'
The JSON deserializer requires only a string.
If you already have the JArray, all you have to do is convert it to a dictionary I guess.
Roughly something like this:
IDictionary<string,object> dict = jarray.ToDictionary(k=>((JObject)k).Properties().First().Name, v=> v.Values().First().Value<object>());
Check this for complete code with an example
I think there might be a better way to convert it to a dictionary though. I'll keep looking.
the JsonConvert.DeserializeObject<T> Method takes a JSON string, in other words a serialized object.
You have a deserialized object, so you'll have to serialize it first, which is actually pointless, considering you have all the information you need right there in the JArray object. If you are aiming just to get the objects from the array as key value pairs, you can do something like this:
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
foreach (JObject content in jarray.Children<JObject>())
{
foreach (JProperty prop in content.Properties())
{
myDictionary.Add(prop.Name, prop.Value);
}
}
To turn your JArray into a string, you'll need to assign the key & values of the dictionary for each element. Mario gave a very accurate approach. But there's a somewhat prettier approach as long as you know how to convert each item into your desired type. The below example is for Dictionary<string, string> but can be applied to any Value type.
//Dictionary<string, string>
var dict = jArray.First() //First() is only necessary if embedded in a json object
.Cast<JProperty>()
.ToDictionary(item => item.Name,
item => item.Value.ToString()); //can be modified for your desired type

Pass complex json via hidden variable and read in mvc 3 controller

I want to do the following.
Pass a complex json object in a hidden input variable
Get that hidden variable through the form collection object.
Convert that hidden text value to a dynamic object which I can loop through to
get the data from it
So I think the first two items above I can do.
$("#hiddenVariableID").val(JSON.stringify(data));
Have a parameter called FormCollection collection in the MVC controller.
Then get the value the following way String data =
collection.Get("hiddenVariableID");
?? Not sure how to do this.
The data I'm passing is an array of objects. The objects are never the same so that is why I need to convert the results in some type of dynamic object that I can loop through.
I can't do an ajax call to do this because I want to stream down the data passed in the hidden variable. So it has to be through a form submission.
Thank you,
-Tesh
You can at that point use some JSON parser to convert between the string and a JSON object you can access dynamically. There are many JSON parsers out there, the code below shows how it can be done with two of them: the JavaScriptSerializer (part of the .NET Framework), and the JSON.NET (a non-MS library, but which IMO is really good).
public static void Test()
{
string JSON = #"[
{'name':'Scooby Doo', 'age':10},
{'name':'Shaggy', 'age':18},
{'name':'Daphne', 'age':19},
{'name':'Fred', 'age':19},
{'name':'Velma', 'age':20}
]".Replace('\'', '\"');
Console.WriteLine("Using JavaScriptSerializer");
JavaScriptSerializer jss = new JavaScriptSerializer();
object[] o = jss.DeserializeObject(JSON) as object[];
foreach (Dictionary<string, object> person in o)
{
Console.WriteLine("{0} - {1}", person["name"], person["age"]);
}
Console.WriteLine();
Console.WriteLine("Using JSON.NET (Newtonsoft.Json) parser");
JArray ja = JArray.Parse(JSON);
foreach (var person in ja)
{
Console.WriteLine("{0} - {1}", person["name"].ToObject<string>(), person["age"].ToObject<int>());
}
}

How do you parse a JSON.NET file without a defined structure?

I'm using an API from OpenCalais that gives me a json string that contains a bunch of JSON objects. The problem is that depending on what I pass into the API the structure of the JSON string changes, which means that I can't cast the deseralization against a custom class I could make. Another problem is that the output isn't in key value form, but rather a complicated object structure. Here is an example of the output-
{"doc":
{"info":
{"allowDistribution":"true",
"allowSearch":"true",
"calaisRequestID":"c1cdd79a-ed89-8431-138c-50e8a37100f9",
"externalID":"17cabs901",
"id":"http://id.opencalais.com/0RCcU306*HTR05*7HlUb5A",
"docId":"http://d.opencalais.com/dochash-1/6188237f-a2a5-3263-95b7-ea894ba98298",
"document":"Bill Gates worked at Microsoft from 2008 to 2011. He is also married to Melinda Gates.",
"docTitle":"",
"docDate":"2012-07-26 15:51:00.885",
"externalMetadata":"",
"submitter":"ABC"}
So you can see there are multiples levels of objects here and there is no key value structure. What I need from this code is essentially all of the name/value info in a dictionary. Then I can sort through based on the keys to the relevant info. It would also be cool if I could somehow also grab the parent of the object value. So for example the output I want is key: allowSearch, value: true, parent: info. I have been trying to mess around with different method of deserialization, dynamic objects, and just plain parsing using functions like .Ancestor and I haven't found anything useful. Any help would be greatly appreciated.
Have you looked at JSON.NET? It can dynamically parse JSON which you can then iterate through:
using Newtonsoft.Json.Linq;
JObject rootObject = JObject.Parse(jsonString);
You can iterate through the children, or search for other nodes like this:
JToken info = rootObject.SelectToken("info");
Json.NET support LINQ to JSON under the Newtonsoft.Json.Linq namespace.
The example to use JObject
JObject o = JObject.Parse(#"{'CPU': 'Intel','Drives': ['DVD read/writer','500 gigabyte hard drive']}");
string cpu = (string)o["CPU"];
// Intel
string firstDrive = (string)o["Drives"][0];
// DVD read/writer
IList<string> allDrives = o["Drives"].Select(t => (string)t).ToList();
// DVD read/writer
// 500 gigabyte hard drive
You can use DeserializeObject which essentially returns a Dictionary<string, object>.
For example:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> myGraph = (Dictionary<string, object>)serializer.DeserializeObject(myJson);
To read stuff from the myGraph dictionary, you will have to cast each step of the way.
For example:
Dictionary<string, object> doc = (Dictionary<string, object>)myGraph["doc"];
Dictionary<string, object> info = (Dictionary<string, object>)doc["info"];
string externalID = (string)info["externalID"];
I'm sure you could genericize it a bit, but I think that should work with the json you posted.

Can you deserialize a JSON string to a C# array?

I'm trying to deserialize the JSON string
[{ "key" : "1", "value" : "open"}, {"key" : "2", "value" : "closed"}, {"key" : "3", "value" : "pending"}]
into a C# array. I'm getting the error "No parameterless constructor defined for type of 'System.Array'." I'm pulling the JSON from a database, then I wanted to deserialize it so I could access the values and update another field in my database with whatever a user passed in. This is just an example that I'm trying though and I need it to be dynamic, not static, since the JSON string contained in the database can be variable.
I tried using a dictionary earlier, but had no luck with that. So I'm trying a different approach now by deserializing it to an array then I was going to populate the dictionary from the array.
This is the method I'm trying to implement with at the moment...although I've tried several others...
IList<Array> ValueArray = new JavaScriptSerializer().Deserialize<IList<Array>>(this.Parameter.ValueList);
//this.Parameter.ValueList just contains my JSON string
I'm thinking that I can't do this without creating my own class?
When I tried using a dictionary, I tried this
Dictionary<string, string> ValueList =
JsonConvert.DeserializeObject<Dictionary<string, string>>(this.Parameter.ValueList);
but received this error
"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,System.String]'
because the type requires a JSON object (e.g. {"name":"value"}) to
deserialize correctly. To fix this error either change the JSON to a
JSON object (e.g. {"name":"value"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array. Path '', line 1, position 1."
So I started to try using an array instead.
var list = new JavaScriptSerializer().Deserialize<List<KeyValue>>(json);
public class KeyValue
{
public string key;
public string value;
}
or just use KeyValue temporarily
var dict = new JavaScriptSerializer().Deserialize<List<KeyValue>>(json)
.ToDictionary(x => x.key, x => x.value);
If you are open to use Json.Net , you can directly convert it to Dictionary
var dict = JsonConvert.DeserializeObject<JArray>(json)
.ToDictionary(x => (string)x["key"], x => (string)x["value"]);
Try
List<Dictionary<string, string>> ValueList = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(this.Parameter.ValueList);
But I'm not sure if it is supported by that library.
I just figured it out. There is specific syntax you need to use for a dictionary. The first thing I checked when first trying to address this problem was my JSON string (I used JSONLint.com), and it is indeed valid, which is what threw me off the scent of the bug...
But I just did a little more testing with it by taking a dictionary and serializing it, to see what the JSON looked like...So what the syntax for my JSON should be for converting to a dictionary is this
{"1":"Pending","2":"Open","3":"Closed"}

Categories

Resources