How to get value of item in JSON array c#? - c#

So, please read this detail for more information. I get error at
Method not found: 'System.String System.String.Format(System.IFormatProvider, System.String, System.Object)'. when i try get value of items of array.
The array is:
{
[
{
"GROUP_MOD_ID": "G06",
"ADMIN": 1,
"USERS": 0
}
]
}
This is snippet code
dynamic obj_str = JsonConvert.DeserializeObject(obj);
string value_admin = obj_str["ADMIN"];
Console.WriteLine(value_admin);
if (value_admin == "1")
return true;
else
return false;
. Thank all.

I wouldn't use dynamic in this case. I generally recommend avoiding dynamic in C#. Instead I prefer the JToken-style approach (in the Newtonsoft.Json.Linq namespace, though it doesn't mean you have to use Linq):
JArray array = JArray.Parse( input );
JObject firstObject = (JObject)array.First;
String adminValue = (String)firstObject.GetValue("ADMIN");
In production you'll want to add input validation code to ensure the input JSON array and object actually has elements and values and handle those errors accordingly.
But if you're certain that the input is correct you can reduce this down to a single-line:
String adminValue = (String)( ((JObject)JArray.Parse( input )).First.GetValue("ADMIN") );
...at the cost of readbility, of course.

First of all your JSON seems to be incorrect.
Correct JSON:
[{
"GROUP_MOD_ID": "G06",
"ADMIN": 1,
"USERS": 0
}]
And when you desialize this json, it will give you array of array.
You code will be:
dynamic obj_str = JsonConvert.DeserializeObject(json);
string value_admin = obj_str[0].ADMIN;
Console.WriteLine(value_admin);
if (value_admin == "1")
{
}
else
{
}
You can see this by doing this way to.
public class SampleClass
{
public string GROUP_MOD_ID { get; set; }
public int ADMIN { get; set; }
public int USERS { get; set; }
}
Code to deserialize:
SampleClass[] obj_str = JsonConvert.DeserializeObject<SampleClass[]>(json);
int value_admin = obj_str[0].ADMIN;
Console.WriteLine(value_admin);
if (value_admin == 1)
{
}
else
{
}

Your code would work only if you have json as
var obj="{'GROUP_MOD_ID':'G06','ADMIN':10,'USERS':0}";
or
var obj="[{'GROUP_MOD_ID':'G06','ADMIN':1,'USERS':0}]";
dynamic obj_str = JsonConvert.DeserializeObject(obj);
string value_admin = obj_str[0]["ADMIN"];
Console.WriteLine(value_admin);

Hi first of you make model for Deserialize Object.
Your model like this.
public class Test_Model
{
[JsonProperty("GROUP_MOD_ID")]
public string GROUP_MOD_ID { get; set; }
[JsonProperty("ADMIN")]
public int ADMIN { get; set; }
[JsonProperty("USERS")]
public int USERS { get; set; }
}
and after write this code:
var obj_str = JsonConvert.DeserializeObject<Test_Model>(obj);
int value_admin = obj_str.ADMIN;
Console.WriteLine(value_admin);
if (value_admin == 1)
return true;
else return false;
I hope so your problem sort out.

Related

How to deserialize this JSON to a List?

I have an issue with deserializing the JSON file from the web to a List.
My code is down below, but it does not execute and shows System.NullReferenceException. It happens in the Content() method, when I call callApiAsync() in the List.
class Program
{
static void Main(string[] args)
{
Content();
Console.ReadKey();
}
private async static void Content()
{
List<Coin> coins = await callApiAsync();
for (int i = 0; i < coins.Count; i++)
{
Console.WriteLine(coins[i].price);
}
}
static async Task<List<Coin>> callApiAsync()
{
string url = "https://api.coinstats.app/public/v1/charts?period=all&coinId=bitcoin";
HttpClient httpClient = new HttpClient();
var httpResponse = await httpClient.GetAsync(url);
string jsonResponse = await httpResponse.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<Root>(jsonResponse);
return data.coins;
}
}
public class Root
{
public List<Coin> coins { get; set; }
}
public class Coin
{
public int time { get; set; }
public int price { get; set; }
}
My JSON for example:
{
"chart":[
[
1372032000,
107.979,
1,
0
],
[
1372118400,
102.982,
1,
0
],
[
1372204800,
103.34,
1,
0
]
]
}
The sample JSON you gave:
{"chart":[[1372032000,107.979,1,0],[1372118400,102.982,1,0],[1372204800,103.34,1,0]]}
Does not have a type that matches the "Root" class you are trying to deserialize to.
You can paste your JSON into a site like https://json2csharp.com/ to find out what the corresponding C# class should look like. In this case, the Root class should look like the following to support deserializing the specified JSON:
public class Root
{
public List<List<double>> chart { get; set; }
}
My guess is that you then intend to interpret the first value in each list as some sort of time stamp, the second value as a "price", and ignore the second and third values in each list. You will have to do the legwork for this after first deserializing the JSON to a list of lists of doubles.
For example:
var data = JsonConvert.DeserializeObject<Root>(jsonResponse);
return data.chart.Select(listOfDoubles => new Coin
{
time = (int)listOfDoubles[0],
price = listOfDoubles[1]
}).ToList();
You only need one string of code to deserialize
return JObject.Parse(jsonResponse)["chart"]
.Select(x => new Coin { time = UnixSecondsToDateTime( (long) x[0]),
price = (decimal)x[1] }
).ToList();
public class Coin
{
public DateTime time { get; set; }
public decimal price { get; set; }
}
public static DateTime UnixSecondsToDateTime(long timestamp, bool local = false)
{
var offset = DateTimeOffset.FromUnixTimeSeconds(timestamp);
return local ? offset.LocalDateTime : offset.UtcDateTime;
}
Unfortunately the API documentations do not tell anything about the response (1, 2).
So, if we can assume that the first number represents an epoch timestamp and the second the average price then you can parse the response with Linq2Json like this
var chart = JObject.Parse(jsonResponse)["chart"] as JArray;
List<(int Time, int Price)> coins = new();
foreach (JArray coin in chart)
{
coins.Add(((int)coin[0], (int)coin[1]));
}

How to parse json data in WPF C#?

I want to parse json data. Below is my json response.
{
"error": true,
"errors": {
"email": [
"Enter a valid email address."
]
}
}
Below is my sample code.
JObject obj = JObject.Parse(res);
string Status = (string)obj["error"];
if (Status == "True" || Status == "true")
{
string email = obj["errors"]["email"].ToString();
MessageBox.Show(email );
return;
}
but I am getting email value is '["Enter a valid email address."]'.
I want to remove '[]'. How to do this?
Unless your schema is dynamic you're almost always better off going with a type-safe approach i.e.:
public class Errors
{
public string[] email { get; set; }
}
public class MyData
{
public bool error { get; set; }
public Errors errors { get; set; }
}
And then deserializing like this:
var json = "{\"error\": true, \"errors\": { \"email\": [\"Enter a valid email address.\"]}}";
var data = JsonConvert.DeserializeObject<MyData>(json);
email in the sample json given in OP, is an array. If you need to access all values in the array, you need to loop through each element in the array. For example
foreach(var emailValue in obj["errors"]["email"])
{
string email = (string)emailValue;
// do rest
}
If you only need the first element in the array, you could use
var email = (string)obj["errors"]["email"][0];

Compare JSON array and JSON object: Cannot convert Array to String error

I am trying to compare json value and based on that i want to update the existing value,for example, currently we have "value" : [r0] in json, i want to compare and if value : [r0] ,then update it to [r0,r1] but iam hiting error that it cannot compare and there is a cast issue, could someone suggest what could be done
public void updateJsonParameter(string file)
{
try
{
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
var jobject = JObject.Parse(file);
var ringvalue = (string)jobject["properties"]["parameters"]["ringValue"]["value"]; // unable to case here and compare
jobject["properties"]["parameters"]["ringValue"]["value"] = array; // able to update value but i want to update after comparing the existing values
var result = JsonConvert.SerializeObject(jobject);
}
following is the json format
{
"properties": {
"displayName": "jayatestdefid",
"description": "test assignment through API",
"metadata": {
"assignedBy": "xyz#gmail.com"
},
"policyDefinitionId": "/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters": {
"ringValue": {
"value": ["r0"]
}
},
"enforcementMode": "DoNotEnforce",
}
}
jobject.properties.parameters.ringValue.value is an array ["r0"] with one element "r0". If you want to check if it's an array with one element and that element is "r0", do exactly that:
var ringvalue = jobject["properties"]["parameters"]["ringValue"]["value"];
if(ringvalue.length == 1 && ringvalue[0] == "r0")
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
You could compare the ringvalue (which is an JArray) using JArray.DeepEquals and then replace if the comparison returns true. For example,
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
JArray valueToCompare = new JArray(new[]{"r0"});
var ringvalue = (JArray)jobject["properties"]["parameters"]["ringValue"]["value"];
if(JArray.DeepEquals(ringvalue,valueToCompare))
{
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
}
First, as Klaycon said in his answer, it's worth noting that your "value" is not a single string. In json, whenever you see [ and ] then you have a collection, or an array, or a list.
When I work with json strings, I always like to be able to convert them into a strongly typed object. There is a very handy online tool I use all the time: http://json2csharp.com/
I took your json string that you provided and pasted it into that website. Here is that your object(s) look like when converted into c# classes:
public class RootObject // You can name this whatever you want
{
public Properties properties { get; set; }
}
public class Metadata
{
public string assignedBy { get; set; }
}
public class RingValue
{
public List<string> value { get; set; }
}
public class Parameters
{
public RingValue ringValue { get; set; }
}
public class Properties
{
public string displayName { get; set; }
public string description { get; set; }
public Metadata metadata { get; set; }
public string policyDefinitionId { get; set; }
public Parameters parameters { get; set; }
public string enforcementMode { get; set; }
}
Now, we can easily do the logic you need as follows:
// This is your json string, escaped and turned into a single string:
string file = "{ \"properties\": { \"displayName\": \"jayatestdefid\", \"description\": \"test assignment through API\", \"metadata\": { \"assignedBy\": \"xyz#gmail.com\" }, \"policyDefinitionId\": \"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test\", \"parameters\": { \"ringValue\": { \"value\": [\"r0\"] } }, \"enforcementMode\": \"DoNotEnforce\", }}";
// Convert your json string into an instance of the RootObject class
RootObject jobject = JsonConvert.DeserializeObject<RootObject>(file);
// Get a list of all the "values"
List<string> values = jobject.properties.parameters.ringValue.value;
// Loop over your colleciton of "value" and do your logic
for (int i = 0; i < values.Count; ++i)
{
if (values[i] == "r0")
{
values[i] = "r0,r1";
}
}
// And finally, turn your object back into a json string
var result = JsonConvert.SerializeObject(jobject);
And this is the final result:
{
"properties":{
"displayName":"jayatestdefid",
"description":"test assignment through API",
"metadata":{
"assignedBy":"xyz#gmail.com"
},
"policyDefinitionId":"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters":{
"ringValue":{
"value":[
"r0,r1"
]
}
},
"enforcementMode":"DoNotEnforce"
}
}

Cannot convert type 'Newtonsoft.Json.Linq.JObject' to Complex Type

I have json as follows,
{
"H": "Macellum",
"M": "Receive",
"A": [
{
"CustomerId": "172600",
"OrderId": "69931",
"OrderStatus": "E0",
"Buy": "A"
}
]
}
and complex type
public class OrderStats
{
public string CustomerId { get; set; }
public string OrderId { get; set; }
public string OrderStatus { get; set; }
public string Buy { get; set; }
}
I am trying a casting as follows,
dynamic obj = JsonConvert.DeserializeObject<dynamic>(message);
OrderStats info = (OrderStats)obj.A[0]; //exception
OrderStats info = obj.A[0] as OrderStats; //info is null
But error as follows
Cannot convert type 'Newtonsoft.Json.Linq.JObject' to OrderStatus
How about this one?
var str = "YOUR_JSON_HERE";
var obj = JsonConvert.DeserializeObject<dynamic>(str);
OrderStats info = ((JArray)obj.A)[0].ToObject<OrderStats>();
I found a solution a bit trivial like this,
dynamic obj = JsonConvert.DeserializeObject<dynamic>(message);
OrderStats info = JsonConvert.DeserializeObject<OrderStats>(JsonConvert.SerializeObject(obj.A[0]));
i`m reviewing this solutions, but i think it's not necessary to use dynamic key,
i did this and it's work for me:
OrderStats info = JsonConvert.DeserializeObject(str)
It's simplified that other lines that you mention, but thanks for the advice, it was
correct for me

JObject.Parse vs JsonConvert.DeserializeObject

What's the difference between JsonConvert.DeserializeObject and JObject.Parse? As far as I can tell, both take a string and are in the Json.NET library. What kind of situation would make one more convenient than the other, or is it mainly just preference?
For reference, here's an example of me using both to do exactly the same thing - parse a Json string and return a list of one of the Json attributes.
public ActionResult ReadJson()
{
string countiesJson = "{'Everything':[{'county_name':null,'description':null,'feat_class':'Civil','feature_id':'36865',"
+"'fips_class':'H1','fips_county_cd':'1','full_county_name':null,'link_title':null,'url':'http://www.alachuacounty.us/','name':'Alachua County'"+ ",'primary_latitude':'29.7','primary_longitude':'-82.33','state_abbreviation':'FL','state_name':'Florida'},"+
"{'county_name':null,'description':null,"+ "'feat_class':'Civil','feature_id':'36866','fips_class':'H1','fips_county_cd':'3','full_county_name':null,'link_title':null,'url':'http://www.bakercountyfl.org/','name':'Baker County','primary_latitude':'30.33','primary_longitude':'-82.29','state_abbreviation':'FL','state_name':'Florida'}]}";
//Can use either JSONParseObject or JSONParseDynamic here
List<string> counties = JSONParseObject(countiesJson);
JSONParseDynamic(countiesJson);
return View(counties);
}
public List<string> JSONParseObject(string jsonText)
{
JObject jResults = JObject.Parse(jsonText);
List<string> counties = new List<string>();
foreach (var county in jResults["Everything"])
{
counties.Add((string)county["name"]);
}
return counties;
}
public List<string> JSONParseDynamic(string jsonText)
{
dynamic jResults = JsonConvert.DeserializeObject(jsonText);
List<string> counties = new List<string>();
foreach(var county in jResults.Everything)
{
counties.Add((string)county.name);
}
return counties;
}
The LINQ-to-JSON API (JObject, JToken, etc.) exists to allow working with JSON without needing to know its structure ahead of time. You can deserialize any arbitrary JSON using JToken.Parse, then examine and manipulate its contents using other JToken methods. LINQ-to-JSON also works well if you just need one or two values from the JSON (such as the name of a county).
JsonConvert.DeserializeObject, on the other hand, is mainly intended to be used when you DO know the structure of the JSON ahead of time and you want to deserialize into strongly typed classes. For example, here's how you would get the full set of county data from your JSON into a list of County objects.
class Program
{
static void Main(string[] args)
{
string countiesJson = "{'Everything':[{'county_name':null,'description':null,'feat_class':'Civil','feature_id':'36865',"
+"'fips_class':'H1','fips_county_cd':'1','full_county_name':null,'link_title':null,'url':'http://www.alachuacounty.us/','name':'Alachua County'"+ ",'primary_latitude':'29.7','primary_longitude':'-82.33','state_abbreviation':'FL','state_name':'Florida'},"+
"{'county_name':null,'description':null,"+ "'feat_class':'Civil','feature_id':'36866','fips_class':'H1','fips_county_cd':'3','full_county_name':null,'link_title':null,'url':'http://www.bakercountyfl.org/','name':'Baker County','primary_latitude':'30.33','primary_longitude':'-82.29','state_abbreviation':'FL','state_name':'Florida'}]}";
foreach (County c in JsonParseCounties(countiesJson))
{
Console.WriteLine(string.Format("{0}, {1} ({2},{3})", c.name,
c.state_abbreviation, c.primary_latitude, c.primary_longitude));
}
}
public static List<County> JsonParseCounties(string jsonText)
{
return JsonConvert.DeserializeObject<RootObject>(jsonText).Counties;
}
}
public class RootObject
{
[JsonProperty("Everything")]
public List<County> Counties { get; set; }
}
public class County
{
public string county_name { get; set; }
public string description { get; set; }
public string feat_class { get; set; }
public string feature_id { get; set; }
public string fips_class { get; set; }
public string fips_county_cd { get; set; }
public string full_county_name { get; set; }
public string link_title { get; set; }
public string url { get; set; }
public string name { get; set; }
public string primary_latitude { get; set; }
public string primary_longitude { get; set; }
public string state_abbreviation { get; set; }
public string state_name { get; set; }
}
Notice that Json.Net uses the type argument given to the JsonConvert.DeserializeObject method to determine what type of object to create.
Of course, if you don't specify a type when you call DeserializeObject, or you use object or dynamic, then Json.Net has no choice but to deserialize into a JObject. (You can see for yourself that your dynamic variable actually holds a JObject by checking jResults.GetType().FullName.) So in that case, there's not much difference between JsonConvert.DeserializeObject and JToken.Parse; either will give you the same result.
JsonConvert.DeserializeObject has one advantage over JObject.Parse:
It is possible to use custom JsonSerializerSettings.
This can be very useful e.g. if you want to control how dates are deserialized.
By default dates are deserialized into DateTime objects.
This means that you may end up with a date with another time zone than the one in the json string.
You can change this behaviour by creating a JsonSerializerSetting and setting
DateParseHandling to DateParseHandling.DateTimeOffset.
An example:
var json = #"{ ""Time"": ""2015-10-28T14:05:22.0091621+00:00""}";
Console.WriteLine(json);
// Result: { "Time": "2015-10-28T14:05:22.0091621+00:00" }
var jObject1 = JObject.Parse(json);
Console.WriteLine(jObject1.ToString());
// Result: { "Time": "2015-10-28T15:05:22.0091621+01:00" }
var jObject2 = Newtonsoft.Json.JsonConvert.DeserializeObject(json,
new Newtonsoft.Json.JsonSerializerSettings
{
DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset
});
Console.WriteLine(jObject2.ToString());
// Result: { "Time": "2015-10-28T14:05:22.0091621+00:00" }
For me the key difference I was interested in was Speed.
I made a simple test to find out if it was faster to use JToken.Parse(string) or DeserializeObject<JToken>(string) to create a large amount of JToken and these were the results after 2,000,000 iterations using a sample of real world data
Method
Operating System Ticks
Milliseconds
JsonConvert
86123945
8612ms
JToken
67671724
6767ms
There was some variation between runs but the difference was always large.
Here is the test so you can modify it or run it yourself:
private static string s = #"{'stream':'btcusdt #bookTicker','data':{'u':20430107433,'s':'BTCUSDT','b':'21223.72000000','B':'3.29440000','a':'21223.73000000','A':'2.05450000'}}";
private static Stopwatch sw = new Stopwatch();
private static void Main(string[] args)
{
JToken convert = default;
sw.Restart();
for (int i = 0; i < 2000000; i++)
{
convert = JsonConvert.DeserializeObject<JToken>(s);
}
Console.WriteLine("JsonConvert: " + sw.ElapsedTicks + " [" + sw.ElapsedMilliseconds + "ms]");
convert.ToString();
convert = default;
sw.Restart();
for (int i = 0; i < 2000000; i++)
{
convert = JToken.Parse(s);
}
Console.WriteLine("JToken : " + sw.ElapsedTicks + " [" + sw.ElapsedMilliseconds + "ms]");
convert.ToString();
Console.ReadLine();
}
I knew an advantage that JsonConvert.DeserializeObject can deserialize an Array/List json text directly, but JObject cannot.
Try below sample code:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace NetCoreJsonNETDemo
{
internal class Person
{
[JsonProperty]
internal string Name
{
get;
set;
}
[JsonProperty]
internal int? Age
{
get;
set;
}
}
internal class PersonContainer
{
public List<Person> Persons
{
get;
set;
}
}
class Program
{
static T RecoverPersonsWithJsonConvert<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
static T RecoverPersonsWithJObejct<T>(string json) where T : class
{
try
{
return JObject.Parse(json).ToObject<T>();
}
catch (Exception ex)
{
Console.WriteLine("JObject threw an Exception: " + ex.Message);
return null;
}
}
static void Main(string[] args)
{
List<Person> persons = new List<Person>();
persons.Add(new Person()
{
Name = "Jack",
Age = 18
});
persons.Add(new Person()
{
Name = "Sam",
Age = null
});
persons.Add(new Person()
{
Name = "Bob",
Age = 36
});
string json = JsonConvert.SerializeObject(persons, new JsonSerializerSettings()
{
Formatting = Formatting.Indented
});
List<Person> newPersons = RecoverPersonsWithJsonConvert<List<Person>>(json);
newPersons = RecoverPersonsWithJObejct<List<Person>>(json);//JObject will throw an error, since the json text is an array.
PersonContainer personContainer = new PersonContainer()
{
Persons = persons
};
json = JsonConvert.SerializeObject(personContainer, new JsonSerializerSettings()
{
Formatting = Formatting.Indented
});
newPersons = RecoverPersonsWithJObejct<PersonContainer>(json).Persons;
newPersons = null;
newPersons = RecoverPersonsWithJsonConvert<PersonContainer>(json).Persons;
Console.WriteLine("Press any key to end...");
Console.ReadKey();
}
}
}
Apart from the answers provided here around usage, which are correct as per me :
Jobject.Parse -> when the Json is not strongly Typed or you do not know the structure of Json ahead of time
JsonConvert.DeserializeObject<T> -> When you know which class or type to cast the Json in. T can be a complex class or a simple type
My answer is based on the performance in case where the structure is not known, as given in the OP code, if we benchmark the usage of both methods for performance, it is observed that Jobject.Parse() fares well in terms of allocated memory, please ignore the name of methods, I am first calling the method with 'JsonConvert.DeserializeObject' and then second method is with Jobject.Parse

Categories

Resources