Construct a JArray with only strings values without a key in C# - 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));

Related

Struggling to deserialize a JSON string using Newtonsoft.JSON in 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);

How can I get the values of some part of a json string?

I'm working with this Json structure, but I don't know how to get the values of the part of the "json" key
I'm using this code to send a request to an API, and the return is an Json object:
var reqData = (HttpWebRequest)WebRequest.Create(string.Format("http://server_ip/system/message/date/{0}/", txtDate.Text));
reqData.ContentType = "application/json";
reqData.Method = "GET";
var answer = (HttpWebResponse)reqData.GetResponse();
List<Dictionary<string, string>> convert = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(answer);
The result is a Json structure like this:
"[
{
\"idMessage\":\"--Message Id--",
\"idTemplate\":--TemplateId--,
\"mail\":\"--mail dir--\",
\"subject\":\"--message subject--\",
\"json\":\"{
\\\"Id\\\":\\\"--Person Id--\\\",
\\\"name\\\":\\\"--Person name--\\\",
\\\"date\\":\\\"--Register date-\\\",
\\\"hour\\\":\\\"--Register hour--\\\"
}\",
\"senddate\":\"--sent date--\",
\"status\":0,
\"template\":null
}
]"
I want to get the values (Id,name,date,hour) from the json part of this Json string, can someone help me to get this values?
That json property contains a string of more JSON, so you have to deserialize that again, the same way you did the whole outer structure.
So now that you have your convert array, you can pull out the first object, grab the value of json and deserialize that:
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(convert[0]["json"]);
Then you can pull each value out like this:
var id = json["Id"];
Mind you, the JSON in your question isn't actually valid. There are a few errors in it. But I'm assuming that they're just copy/paste errors and the web service is actually returning valid JSON.

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:

JsonConvert.DeserializeObject generates a null dynamic object

I'm attempting to deserialize a response from a REST API using JSON.NET.
dynamic resultObject = JsonConvert.DeserializeObject(responseText);
I'd like to not have to define classes for the different kinds of responses the REST API returns, as it changes often. I'd like to take advantage of dynamic runtime variables.
In VS2015, I've added watchers to see the values directly after the line of code above executes.
resultObject resolves to a null object, however, the watcher shows that the line code run directly results in aNewtonsoft.Json.Linq.JObject which is populated with the deserialized response string.
Why doesn't the dynamic var resultObject populate with the JObject?
var responseStream = e.Response?.GetResponseStream();
string responseText = "";
if (responseStream != null)
{
using (var reader = new StreamReader(responseStream))
{
responseText = reader.ReadToEnd();
}
dynamic responseObject = JsonConvert.DeserializeObject(responseText);
foreach (var error in responseObject["errors"].Children())
{
errors.Add(error.Val);
}
}
UPDATE:
Contents of the JSON to parse:
JSON updated to remove debug information - problem persists.
https://jsonblob.com/57cb00c7e4b0dc55a4f2abe9
UPDATE 2:
It appears that JsonConvert.DeserializeObject() is parsing my JSON to have extra brackets around the entire object.
String as it is generated from the response stream:
"{\"message\":\"422 Unprocessable Entity\",\"errors\":[[\"The email must be a valid email address.\"],[\"The password must be at least 8 characters.\"]],\"status_code\":422}"
value of JsonConvert.DeserializeObject():
{{
"message": "422 Unprocessable Entity",
"errors": [
[
"The email must be a valid email address."
],
[
"The password must be at least 8 characters."
]
],
"status_code": 422
}}
UPDATE 3:
Converting to JObject.Parse resulted in the same output.
I changed the variable from type dynamic to JObject - to accept the response from JObject.Parse() and still the variable is set to null.
I think, JSonConvert is invalid for solve your task. You can simply use JObject and JObject.Parse and then iterate "errors" property by Item
Your problem is that, in the following line, you are assuming that "errors" is an array of JSON objects, each with a property named "Val":
foreach (var error in responseObject["errors"].Children())
{
errors.Add(error.Val);
}
However, "errors" is actually an array of arrays, and so error.Val evaluates to null. Instead you need to do something like:
var errors = new List<string>();
dynamic responseObject = JsonConvert.DeserializeObject(responseText);
foreach (dynamic errorList in responseObject["errors"].Children())
{
foreach (dynamic error in errorList.Children())
{
errors.Add((string)error);
}
}
Personally, however, I recommend avoiding use of dynamic because you lose the advantages of static, compile-time type checking. Code full of dynamic objects can also be hard to debug. Instead I would recommend the use of LINQ to JSON, specifically the SelectTokens() along with the JSONPath recursive descent operator ..* to pick out all string values inside the "errors" object like so:
var token = JToken.Parse(responseText);
var errors = token.SelectTokens("errors..*") // Iterate through all descendants of the "errors" property
.OfType<JValue>() // Filter those that are primitive values
.Select(v => (string)v) // Convert to their string values
.ToList(); // And evaluate the query as a list.
Example fiddle.

JContainer, JObject, JToken and Linq confusion

I am having trouble understanding when to use JContainer, JObject, and JToken. I understand from the "standards" that JObject is composed of JProperties and that JToken is the base abstract class for all of the JToken types, but I don't understand JContainer.
I am using C# and I just bought LinqPad Pro 5.
I have a JSON data source in a file, so I'm deserializing that file's contents successfully using this statement:
string json;
using (StreamReader reader = new StreamReader(#"myjsonfile.json"))
{
json = reader.ReadToEnd();
}
At that point, I take the JSON string object and deserialize it to a JObject (and this might be my mistake--perhaps I need to make jsonWork a JToken or JContainer?):
JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);
In my JSON data (the string represented by JSON), I have three objects--the top-level object look similar to this:
{
"Object1" : { ... },
"Object2" : { ... },
"Object3" : { ... }
}
Each object is composed of all sorts of tokens (arrays, strings, other objects, etc.), so it is dynamic JSON. (I used ellipses as placeholders rather than muddying up this question wit lots of JSON data.)
I want to process "Object1", "Object2", and "Object3" separately using LINQ, however. So, ideally, I would like something like this:
// these lines DO NOT work
var jsonObject1 = jsonWork.Children()["Object1"]
var jsonObject2 = jsonWork.Children()["Object2"]
var jsonObject3 = jsonWork.Children()["Object3"]
But the above lines fail.
I used var above because I have no idea what object type I should be using: JContainer, JObject, or JToken! Just so you know what I want to do, once the above jsonObject# variables are properly assigned, I would like to use LINQ to query the JSON they contain. Here is a very simple example:
var query = from p in jsonObject1
where p.Name == "Name1"
select p
Of course, my LINQ ultimately will filter for JSON arrays, objects, strings, etc., in the jsonObject variable. I think once I get going, I can use LinqPad to help me filter the JSON using LINQ.
I discovered that if I use:
// this line WORKS
var jsonObject1 = ((JObject)jsonWork).["Object1"];
Then I get an JObject type in jsonObject1. Is this the correct approach?
It is unclear to me when/why one would use JContainer when it seems that JToken and JObject objects work with LINQ quite well. What is the purpose of JContainer?
You don't really need to worry about JContainer in most cases. It is there to help organize and structure LINQ-to-JSON into well-factored code.
The JToken hierarchy looks like this:
JToken - abstract base class
JContainer - abstract base class of JTokens that can contain other JTokens
JArray - represents a JSON array (contains an ordered list of JTokens)
JObject - represents a JSON object (contains a collection of JProperties)
JProperty - represents a JSON property (a name/JToken pair inside a JObject)
JValue - represents a primitive JSON value (string, number, boolean, null)
So you see, a JObject is a JContainer, which is a JToken.
Here's the basic rule of thumb:
If you know you have an object (denoted by curly braces { and } in JSON), use JObject
If you know you have an array or list (denoted by square brackets [ and ]), use JArray
If you know you have a primitive value, use JValue
If you don't know what kind of token you have, or want to be able to handle any of the above in a general way, use JToken. You can then check its Type property to determine what kind of token it is and cast it appropriately.
JContainer is a base class for JSON elements that have child items. JObject, JArray, JProperty and JConstructor all inherit from it.
For example, the following code:
(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")
Would throw an InvalidCastException, but if you cast it to a JContainer, it would be fine.
Regarding your original question, if you know you have a JSON object at the top level, you can just use:
var jsonWork = JObject.Parse(json);
var jsonObject1 = jsonWork["Object1"];
Most examples have simple json and I've googled "C# Newtonsoft parse JSON" more than once.
Here's a bit of a json file I was just asked to parse for a csv. The company name value is nested within many arrays / objects so it is semi-complicated in that regard.
{
"page": {
"page": 1,
"pageSize": 250
},
"dataRows": [
{
"columnValues": {
"companyName": [
{
"name": "My Awesome Company",
}
]
}
}
]
}
var jsonFilePath = #"C:\data.json";
var jsonStr = File.ReadAllText(jsonFilePath);
// JObject implementation for getting dataRows JArray - in this case I find it simpler and more readable to use a dynamic cast (below)
//JObject jsonObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
//var dataRows = (JArray)jsonObj["dataRows"];
var dataRows = ((dynamic)JsonConvert.DeserializeObject(jsonStr)).dataRows;
var csvLines = new List<string>();
for (var i = 0; i < dataRows.Count; i++)
{
var name = dataRows[i]["columnValues"]["companyName"][0]["name"].ToString();
// dynamic casting implemntation to get name - in this case, using JObject indexing (above) seems easier
//var name2 = ((dynamic)((dynamic)((dynamic)dataRows[i]).columnValues).companyName[0]).name.ToString();
csvLines.Add(name);
}
File.WriteAllLines($#"C:\data_{DateTime.Now.Ticks}.csv", csvLines);

Categories