Struggling to deserialize a JSON string using Newtonsoft.JSON in C# - c#

I'm struggling to deserialize a JSON string to an object in C#.
The string in question is
{"Hallway":2,"Hot Water":7,"Kitchen":4,"Landing":6,"Living Room":3,"Office":1,"Utility":5}
My current code is:
dynamic response = JsonConvert.DeserializeObject<dynamic>(outputData);
Dictionary<string,int> Zones = new Dictionary<string, int>();
foreach (dynamic Temp in response)
{
Zones.Add(Temp.Name, 1);
}
outputData is the raw JSON string above and comes from an IoT device.
The code above works such that I get the names into the dictionary object but I'd like to capture the number as well i.e. replace the 1 with the correct number.
I've tried Temp.Value and Temp.First.Value which errors with:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best overloaded method match for 'System.Collections.Generic.Dictionary.Add(string, int)' has some invalid arguments'

There's no need for the loop or dynamic at all, you can deserialise directly to a dictionary:
var Zones = JsonConvert.DeserializeObject<Dictionary<string, int>>(json);
PS Every time you use dynamic, a kitten dies...

You can deserialize to a Dictionary<string,int> directly :
var dict=JsonConvert.DeserializeObject<Dictionary<string,int>>(json);

Instead of
Zones.Add(Temp.Name, 1);
you need
Zones.Add(Temp.Name, (int) Temp.Value);

Related

How to convert a JSON object containing an array to C# Dictionary<string,string>?

I am sending a request to a WebAPI using following code:
client.PostAsync(baseAddress + path, new FormUrlEncodedContent(JsonConvert.DeserializeObject<Dictionary<string,string>>(form)))
where client is an object of HttpClient class. This code is executed for all the requests to the WebApi. I am trying to send following data to the API:
{
"code":"GUEST",
"category":"Indian",
"sections":["01000000-0000-0000-0000-000000000000","02000000-0000-0000-0000-000000000000"],
"date":"0001-01-01T00:00:00",
"time":"0001-01-01T00:00:00",
"quantity":1.0,
"price":0.0,
"discount":0.0,
"paymentMethod":"ID",
"paymentMethodID":null,
"ticketNo":null
}
Now because the FormUrlEncodedContent accepts only the Dictionary<string,string> object, I am converting this JSON into that type using NewtonSoft's JSON.NET method JsonConvert.DeserializeObject. But at the point where sections array starts, it is showing me this error message:
Unexpected character encountered while parsing value:[. Path 'sections'.
So, what approach should I follow if I want to use the same code for this kind of JSON data?
If you for any reason need to send all values as strings, then you must convert array of strings to string before deserializing it to Dictionary<string, string>.
It can be done like this:
var json = "{\"code\":\"GUEST\",\"category\":\"Indian\",\"sections\":[\"01000000-0000-0000-0000-000000000000\",\"02000000-0000-0000-0000-000000000000\"],\"date\":\"0001-01-01T00:00:00\",\"time\":\"0001-01-01T00:00:00\",\"quantity\":1.0,\"price\":0.0,\"discount\":0.0,\"paymentMethod\":\"ID\",\"paymentMethodID\":null,\"ticketNo\":null}";
var jObject = JObject.Parse(json);
jObject["sections"] = JsonConvert.SerializeObject(jObject["sections"].ToObject<string[]>());
var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(jObject.ToString());
That way you will get result:

Construct a JArray with only strings values without a key in C#

I would highly appreciate if someone helped me out with constructing a JArray in C# by only using values and no key. Here is an example of the what I want:
{[
"ZGVyZWtAcG9zc2tpLmNvbQ==",
"YW5kcmVAbGltYWcubmV0",
"YW5keUBiYW9iYW9tYWlsLmNvbQ==",
"dGVzdEBraW5ub3YuY29t",
"c2hhaG5hd2F6LmFsYW0xM0Bob3RtYWlsLmNvbQ==",
"YnJlYW5uQGVtYWlsLmNvbQ=="
]}
Here is the code I wrote for it but I am getting an exception because when I declare JObject, it requires me to have a key and a value, but i only need the value as I am sending this array as a parameter to an API, and they need it in a specific format.
Here is my code that causes the issue:
var recipients = new JArray();
foreach (var c in retrievedContacts.recipients)
{
var jsonObject = new JObject();
jsonObject.Add(c.id);
recipients.Add(jsonObject);
}
dynamic addToListResponse = await sg.client.contactdb.lists._(listJson.lists[0].id).recipients.post(requestBody: recipients);
The last line sends a post request to SendGrid. Here the list id is valid, everything is ok except for adding json object in the loop. Please Help!
To create a JArray with specified values, you can use JToken.FromObject() to convert your c.id to a JToken, then construct your JArray as follows:
var recipients = new JArray(retrievedContacts.recipients.Select(c => JToken.FromObject(c.id)));
In particular, this works if id is a byte array. In this case Json.Net will convert it to a base64 string. Sample fiddle.
If c.id is already a string (in your question, you don't specify its type), you can skip the call to FromObject() and add it as-is without serialization:
var recipients = new JArray(retrievedContacts.recipients.Select(c => c.id));

Retrieving an array from JSON in ASP.net C#

I'm gathering data from a web API which returns a complex JSON string. This contains values of many different types, a few arrays, and some fairly deep nesting.
Currently I'm converting the string to a dynamic object like so:
dynamic dynamicObject = JsonConvert.DeserializeObject(jsonString);
Then I'm retrieving values from this object as needed and typecasting them, however this method gives a null reference exception when I attempt to retrieve an array:
int myValue = (int)dynamicObject.foo.value; // Works!
int[] myArrayOfInts = (int[])dynamicObject.bar.values; // Null
I'm not sure how to proceed as I'm fairly new to C# and ASP.net. Most of the solutions I have come across so far require the creation of small, strictly-typed classes which mirror the entire JSON structure. In my case it would be preferable to simply use a dynamic object, partly for simplicity and partly because only certain values are actually being used.
When I try to run your code, I get a RuntimeBinderException: Cannot convert type 'Newtonsoft.Json.Linq.JArray' to 'int[]'. You can do this conversion with ToObject.
dynamic dynamicObject = JsonConvert.DeserializeObject("{\"values\": [1, 3, 4]}");
int[] myArrayOfInts = dynamicObject.values.ToObject<int[]>();
The cast to int works because a casting conversion is defined for many types including int, but not int[].
You could deserialize the array using the ToObject<type> extension method (where type is the desired data type):
var jsonString = #"{ ""name"":""test"", ""array"": [""10"",""20"",""30"",""40""] }";
dynamic dynamicObject = JsonConvert.DeserializeObject(jsonString);
Console.WriteLine(((string)dynamicObject.name));
var items = dynamicObject.array.ToObject<int[]>();
foreach (var item in items)
{
Console.WriteLine(item);
}
The output is:
test
10
20
30
40
Another possibility would be to cast the object to JObject and then fetch the array as a property - the retrieved object is automatically of type JToken, which allows iteration:
var array = ((JObject)dynamicObject)["array"];
foreach (var item in array)
{
Console.WriteLine(item.ToString());
}

Turn a JSON string into a dynamic object

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.

Converting a KeyValuePair collection in to anonymous type

Is it possible to convert a a IEnumerable<KeyValuePair<string,string>> of KeyValuePair to an anonymous type?
Dictionary<string, string> dict= new Dictionary<string, string>();
dict.add("first", "hello");
dict.add("second", "world");
var anonType = new{dict.Keys[0] = dict[0], dict.Keys[1] = dict[1]};
Console.WriteLine(anonType.first);
Console.WriteLine(anonType.second);
********************output*****************
hello
world
The reason i would like to do this is because I am retrieving an object from a webservice that represents an object that does not exist in the wsdl. The returned object only contains a KeyValuePair collection that contains the custom fields and their values. These custom fields can be named anything, so i cant really map an xml deserialization method to the final object i will be using (whose properties must be bound to a grid).
*Just because I used Dictionary<string,string> does not mean it is absolutely a dictionary, i just used it for illustration. Really its an IEnumerable<KeyValuePair<string,string>>
Ive been trying to thing of a way to do this, but am drawing a blank. This is c# .NET 4.0.
You could use the ExpandoObject, it is based on a dictionary.
I think there are a lot of ways to achieve this, but actually converting it in the same Dictionary seems a bit odd to do.
One way to accomplish this, by not actually converting everyting is the following:
public class MyDictionary<T,K> : Dictionary<string,string> // T and K is your own type
{
public override bool TryGetValue(T key, out K value)
{
string theValue = null;
// magic conversion of T to a string here
base.TryGetValue(theConvertedOfjectOfTypeT, out theValue);
// Do some magic conversion here to make it a K, instead of a string here
return theConvertedObjectOfTypeK;
}
}
ExpandoObject is the best option, which I believe is a wrapper around some XML. You could also use an XElement:
var result = new XElement("root");
result.Add(new XElement("first", "hello"));
result.Add(new XElement("second", "world"));
Console.WriteLine(result.Element("first").Value);
Console.WriteLine(result.Element("second").Value);
foreach (var element in result.Elements())
Console.WriteLine(element.Name + ": " + element.Value);
I haven't used ExpandoObject, so I'd try that first because I understand it does exactly what you want and is also something new and interesting to learn.

Categories