I have the following Json (is a file attached to the project):
{
"Errors": {
"NoCountry": {
"MSG": "The CountryCode field is required.",
"Description": "Error encountered when Country parameter is missing from the request"
},
"NoLOI": {
"MSG": "Validation failed: \r\n -- LengthOfInterview cannot be empty"
"Description": "Error encountered when LOI parameter is missing from the request"
}
}
}
I need to extract the values for e.g. Errors.NoCompletes.MSG in order to use it in an assert to compare it with an output that i get from the API.
Till now i tried to create a dictionary that looks like this:
public class ErrorsDictionary
{
public string MSG;
public string Description;
}
public class DicRoot
{
public Dictionary<string, ErrorsDictionary> Errors { set; get; }
}
And use it like this:
DicRoot Json = JsonConvert.DeserializeObject<DicRoot>(File.ReadAllText(#"c:\users\banu_\source\repos\TestJsonLib\TestJsonLib\Json\ErrorMSG.json"));
foreach (var f in Json.Errors)
{
Console.WriteLine("Nume={0} Mesaj={1} Description={2}",f.Key, f.Value.MSG, f.Value.Description);
}
The problem is that i cannot figure out, how can i extract a specific value, like what i said above for Errors.NoLOI.MSG, in order to be able to use it in an assert like Assert.Equals(ex, MyParam);
You can also use JsonPath, anonymous types and string interpolation if you like:
JObject obj = JObject.Parse(json);
var errors = obj
.SelectTokens("$.Errors.*")
.ToDictionary(
e => ((JProperty)e.Parent).Name,
e => new { Msg = e["MSG"], Descr = e["Description"] });
foreach (var e in errors)
{
Console.WriteLine($"Nume={e.Key} Mesaj={e.Value.Msg} Description={e.Value.Descr}");
}
I think what you are asking for is this?
DicRoot dict = JsonConvert.DeserializeObject<DicRoot>(File.ReadAllText("foo.json"));
string msg = dict["NoLOI"].MSG;
I know this looks like a bit working around. However, it's working.
class Program
{
static void Main(string[] args)
{
string json = "{\"Errors\": {\"NoCountry\": {\"MSG\": \"The CountryCode field is required.\",\"Description\": \"Error encountered when Country parameter is missing from the request\"},\"NoLOI\": {\"MSG\": \"Validation failed: \r\n -- LengthOfInterview cannot be empty\", \"Description\": \"Error encountered when LOI parameter is missing from the request\"},}}";
var Json = JsonConvert.DeserializeObject<ErrorsClass>(json);
var obj = JsonConvert.DeserializeObject<Dictionary<string, ErrorsDictionary>>(Json.Errors.ToString());
foreach (var f in obj)
{
Console.WriteLine("Nume={0} Mesaj={1} Description={2}", f.Key, f.Value.MSG, f.Value.Description);
}
Console.Read();
}
}
public class ErrorsDictionary
{
public string MSG { get; set; }
public string Description { get; set; }
}
public class DicRoot
{
public Dictionary<string, ErrorsDictionary> ErrorsDic { set; get; }
}
class ErrorsClass
{
public object Errors { get; set; }
}
Output:
Nume=NoCountry Mesaj=The CountryCode field is required. Description=Error encountered when Country parameter is missing from the request
Nume=NoLOI Mesaj=Validation failed:
-- LengthOfInterview cannot be empty Description=Error encountered when LOI parameter is missing from the request
You can use Newtonsoft.json NuGet. Try this
var files = JObject.Parse(YourJson);
var recList = files.SelectTokens("$..Errors").ToList();
foreach (JProperty prop in recList.Children())
{
string key = prop.Name.ToString();
string value = prop.Value.ToString();
//Do your stuffs here
}
Related
Am new to C# and I have an HTTP response which i have converted to a json object via
var result = await response.Content.ReadAsStringAsync();
dynamic jsonResponse = JsonConvert.DeserializeObject(result);
When i Debug.WriteLine((object)jsonResponse); am now getting
{
"status": false,
"data":
{
"message": "Incorrect Username or Password",
"name": "Failed Login"
}
}
Which is as i expect. But the problem comes in reading it i have tried
if ((object)jsonResponse.status != true){ //throws an error
...do stuff
}
The above if statement throws an error
the operand != cannot be applied to operands of type boolean and object
by altering the code and adding
if ((bool)(object)jsonResponse.status != true){ //throws an error
...do stuff
}
the above throws an error
Unable to cast object of type NewtonSoft.Json.Linq.Jvalue to system.boolean
What else do i need to add?
but when i run
Debug.WriteLine((object)jsonResponse.status)
the value is true.
Where am I wrong?
add classes for your response
public class Data
{
public string message { get; set; }
public string name { get; set; }
}
public class LoginResponse
{
public bool status { get; set; }
public Data data { get; set; }
}
then convert response to class
var response = JsonConvert.DeserializeObject<LoginResponse>(result);
and use it
if(!response.status){
//do staff
}
Create classes and deserialize response to it:
public class Data
{
public string message {get;set;}
public string name {get;set;}
}
public class Response
{
public bool status {get;set;}
public Data data {get;set;}
}
var jsonResponse = JsonConvert.DeserializeObject<Response>(result);
if (!jsonResponse.status){
//your code
}
This is not the correct way to read a Json. You can access them one by one, along the way as you come down reading the file.
As in your code below:
{
"status": false,
"data": {
"message": "Incorrect Username or Password",
"name": "Failed Login"
}
}
You will need to access it like this:
JsonObject json = JsonObject.Parse(data);
var statusObject = json.GetNamedBoolean("status");
var dataObject = json.GetNamedObject("data");
var message = dataObject.GetNamedString("message");
var name = dataObject.GetNamedString("name");
// if you need to check whether the `Json` contains the object or not
// check it with
if (dataObject.ContainsKey("message"))
{
// get the value here as above
}
I am receiving the following JSON object as a server response to a GET request:
{{ "data": [ { "role_id": "1", "role_name": "Administrator" }, { "role_id": "2", "role_name": "Operator" } ]}}
I am trying to create an array of "role_id" and a separate array of "role_name". Then, I want to add each member of the "role_name" array to a combobox. right now I am using Newtonsoft.Json.Linq to do the following:
JObject par = JObject.Parse(res);
foreach(string s in (string)par["data"]))
{
}
string role = (string)par["data"]["role_id"];
string name = (string)par["data"]["role_name"];
this.cmbRoleID.Items.Add(name.ToString());
I'm wondering how I can use a foreach loop or something to make this happen no matter how many pairs of role_id and role_name are sent in the {{"data":[]}}.
Why not deserialize the json string into a class?
Create your classes that map to a JSON structure of yours
public class Data
{
public string role_id { get; set; }
public string role_name { get; set; }
}
public class RootObject
{
public List<Data> data { get; set; }
}
Then deserialize it and loop through like you normally would when looping array of objects.
var result = JsonConvert.DeserializeObject<RootObject>(res);
foreach(var item in result.data)
{
//item.role_id, item.role_name
//Your logic here.
}
Simple. Minimal lines of code if you use "dynamic". For:
{
"data":[
{
"role_id":"1",
"role_name":"Administrator"
},
{
"role_id":"2",
"role_name":"Operator"
}
]
}
Do something like this:
dynamic parsedObj = JsonConvert.DeserializeObject(json);
foreach(var child in parsedObj.data)
{
var roleId = child.role_id;
var roleName = child.role_name;
//now do something with them.
}
You can use a for loop to loop through the JSON like this:
JObject par = JObject.Parse(res);
foreach(JToken data in par["data"].Children()))
{
string role = data["role_id"].ToString();
string name = data["role_name"].ToString();
this.cmbRoleID.Items.Add(name);
}
I am using a web service to get response and found the Json is not in the right format. Please see the below sample.
The Object structure is :
public class Action
{
public string serialNumber { get; set; }
public string method1 { get; set; }
public string recipient1 { get; set; }
public string notifyon1 { get; set; }
}
We having a field "recipient1" which has value "1#test.com,2#test.com,3#test.com" then the api response the json as below.
Bad json response :
{"serialNumber": "2471",
"method1": "email",
"recipient1": "1#test.com",
"2#test.com": "",
"3#test.com": "",
"notifyon1": "warning",
"critical": ""}
Which is supposed to be :
{"serialNumber": "2471",
"method1": "email",
"recipient1": "1#test.com,2#test.com,3#test.com",
"notifyon1": "warning,critical"}
First I was trying to using regex to convert these emails values to the right field. But then I found it is happened for all the value which include comma "," . Such as ”Notifyon1“ in the above sample.
Now I am thinking if there is any way I can do parse the json, when it find "2#test.com" then check the Object, if it is not a property then put it as a value into previous field "recipient1".
Thanks for all your help.
This will work regardless of empty values in the properties.
using Newtonsoft.Json;
private Action HandleBadJson(string badJson)
{
Dictionary<string, string> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(badJson);
Action act = new Action();
List<string> propertyNames = act.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Select(p => p.Name).ToList();
string currentProperty = "";
foreach (var keyValPair in dictionary)
{
if (propertyNames.Contains(keyValPair.Key))
{
currentProperty = keyValPair.Key;
act.GetType().GetProperty(currentProperty).SetValue(act, keyValPair.Value);
continue;
}
else
{
var currentValue = act.GetType().GetProperty(currentProperty).GetValue(act, null);
string value = currentValue + "," + keyValPair.Key;
value = value.Trim(',');
act.GetType().GetProperty(currentProperty).SetValue(act, value);
}
}
return act;
}
I have the following issue with this json :
{
"EVTS": {
"EVT": [
{ "ID": "123456",
"KEY1" : "somekey",
"CATEG": [
"cat1",
"cat2",
"cat3"
]
}
]}
}
and this c# class:
public class myClass{
public string ID { get; set; }
public string KEY1 { get; set; }
public list<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
}
here i call the deserializer :
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
But this last code doesnt work, i throws this exception : System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List1[System.String].`
Instead of list<string> i used string [] and only string nothing seems to work.
how can i deserialize this object correctly please.
Thank you.
There doesn't seem to be any apparent problem wit hyour code as this working example illustrates:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
public class myClass
{
public string ID { get; set; }
public string KEY1 { get; set; }
public List<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
class Program
{
static void Main()
{
string json =
#"{
""EVTS"": {
""EVT"": [
{
""ID"": ""123456"",
""KEY1"": ""somekey"",
""CATEG"": [
""cat1"",
""cat2"",
""cat3""
]
}
]
}
}";
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
foreach (string item in globalobject.EVTS.EVT[0].CATEG)
{
Console.WriteLine(item);
}
}
}
Maybe you just fed a wrong json value to the deserializer which doesn't look like as the one shown in your question. By the way, the one shown i nyour question is invalid JSON as you are missing a , after KEY1 property declaration.
UPDATE:
Now that you have shown your real JSON (coming from http://donnees.ville.quebec.qc.ca/Handler.ashx?id=69&f=JSON) it appears that there's a row where CATEG is not an array of strings but a simple string:
""CATEG"": ""Conférence""
Now that's a pretty bad design because they are mixing arrays and simple properties. I am afraid that in order to deal with this situation you will need to use JObjects and extract the information you need by testing the actual underlying type.
For example:
var obj = JObject.Parse(json);
var events = (JArray)obj["EVTS"]["EVT"];
foreach (JObject evt in events)
{
var categories = evt["CATEG"];
if (categories is JArray)
{
// you've got a list of strings so you can loop through them
string[] cats = ((JArray)categories)
.Select(x => x.Value<string>())
.ToArray();
}
else
{
// you've got a simple string
string cat = categories.Value<string>();
}
}
I have done this many times with many many headaches. My advice is take the json output and use a tool similar to this to write your class for you (http://json2csharp.com/).
Then go over any nullable variables and add nullable type (ex. using int? for int) where needed.
I have an array of objects like this in json format:
{"results":[{"SwiftCode":"","City":"","BankName":"Deutsche Bank","Bankkey":"10020030","Bankcountry":"DE"},{"SwiftCode":"","City":"10891 Berlin","BankName":"Commerzbank Berlin (West)","Bankkey":"10040000","Bankcountry":"DE"}]}
What I want to get is a object[] in C#, where one object contains all the data what is in one json object. The thing is, I can NOT make a class with the properties of this object like here:
public class Result
{
public int SwiftCode { get; set; }
public string City { get; set; }
// .
// .
public string Bankcountry { get; set; }
}
Because I get everytime different results back, but I know it's always an array of objects. Someone knows how I could manage to get an array of objects back?
EDIT
I have to pass this object to powershell via WriteObject(results). So the ouput should only be the object IN the array.
Though this is an old question, I thought I'd post my answer anyway, if that helps someone in future
JArray array = JArray.Parse(jsonString);
foreach (JObject obj in array.Children<JObject>())
{
foreach (JProperty singleProp in obj.Properties())
{
string name = singleProp.Name;
string value = singleProp.Value.ToString();
//Do something with name and value
//System.Windows.MessageBox.Show("name is "+name+" and value is "+value);
}
}
This solution uses Newtonsoft library, don't forget to include using Newtonsoft.Json.Linq;
Use newtonsoft like so:
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
class Program
{
static void Main()
{
string json = "{'results':[{'SwiftCode':'','City':'','BankName':'Deutsche Bank','Bankkey':'10020030','Bankcountry':'DE'},{'SwiftCode':'','City':'10891 Berlin','BankName':'Commerzbank Berlin (West)','Bankkey':'10040000','Bankcountry':'DE'}]}";
var resultObjects = AllChildren(JObject.Parse(json))
.First(c => c.Type == JTokenType.Array && c.Path.Contains("results"))
.Children<JObject>();
foreach (JObject result in resultObjects) {
foreach (JProperty property in result.Properties()) {
// do something with the property belonging to result
}
}
}
// recursively yield all children of json
private static IEnumerable<JToken> AllChildren(JToken json)
{
foreach (var c in json.Children()) {
yield return c;
foreach (var cc in AllChildren(c)) {
yield return cc;
}
}
}
}
Use NewtonSoft JSON.Net library.
dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
Hope this helps.
I have just got an solution a little bit easier do get an list out of an JSON object. Hope this can help.
I got an JSON like this:
{"Accounts":"[{\"bank\":\"Itau\",\"account\":\"456\",\"agency\":\"0444\",\"digit\":\"5\"}]"}
And made some types like this
public class FinancialData
{
public string Accounts { get; set; } // this will store the JSON string
public List<Accounts> AccountsList { get; set; } // this will be the actually list.
}
public class Accounts
{
public string bank { get; set; }
public string account { get; set; }
public string agency { get; set; }
public string digit { get; set; }
}
and the "magic" part
Models.FinancialData financialData = (Models.FinancialData)JsonConvert.DeserializeObject(myJSON,typeof(Models.FinancialData));
var accounts = JsonConvert.DeserializeObject(financialData.Accounts) as JArray;
foreach (var account in accounts)
{
if (financialData.AccountsList == null)
{
financialData.AccountsList = new List<Models.Accounts>();
}
financialData.AccountsList.Add(JsonConvert.DeserializeObject<Models.Accounts>(account.ToString()));
}
Using .NET 6 you could use built in System.Text.Json.Nodes
Example:
string json = #"{""results"":[{""SwiftCode"":"""",""City"":"""",""BankName"":""Deutsche Bank"",""Bankkey"":""10020030"",""Bankcountry"":""DE""},{""SwiftCode"":"""",""City"":""10891 Berlin"",""BankName"":""Commerzbank Berlin (West)"",""Bankkey"":""10040000"",""Bankcountry"":""DE""}]}";
JsonObject obj = JsonNode.Parse(json).AsObject();
JsonArray jsonArray = (JsonArray)obj["results"];
I believe this is much simpler;
dynamic obj = JObject.Parse(jsonString);
string results = obj.results;
foreach(string result in result.Split('))
{
//Todo
}