We have the following Json
{
"#message": "some message",
"outputs": {
"outone": {
"value": "eastus2"
},
"outtwo": {
"value": "r7ty-network"
}
}
}
the outputs section contain 2 objects "outone" and "outtwo", we are struggling to get hold of the the names "outone" and "outtwo" and its corresponding value property.
we generated c# classes and everything was working as expected, but later we were told that the values "outone" and "outtwo",are dynamic, they can be named anything.
any pointers will help.
Thanks -Nen
try this code using Newtonsoft.Json
var jsonDeserialized= JsonConvert.DeserializeObject<Data>(json);
and classes
public partial class Data
{
[JsonProperty("#message")]
public string Message { get; set; }
[JsonProperty("outputs")]
public Dictionary<string,Out> Outputs { get; set; }
}
public partial class Out
{
[JsonProperty("value")]
public string Value { get; set; }
}
I assume you want to have some kind of key value list. Here's a demo in form of a test that's green:
UPDATE: Took care of eventual duplicate "keys"
[TestMethod]
public void JObject_Test()
{
var jObject = JObject.Parse(
#"{
""#message"": ""some message"",
""outputs"": {
""outone"": {
""value"": ""eastus2""
},
""outtwo"": {
""value"": ""r7ty-network""
}
}
}");
var outputs = new List<KeyValuePair<string, string>>();
foreach (var jproperty in jObject["outputs"].Children<JProperty>())
{
outputs.Add(
new KeyValuePair<string, string>(jproperty.Name,
(string)((JObject)jproperty.Value)["value"]));
}
Assert.AreEqual("outone", outputs[0].Key);
Assert.AreEqual("eastus2", outputs[0].Value);
Assert.AreEqual("outtwo", outputs[1].Key);
Assert.AreEqual("r7ty-network", outputs[1].Value);
}
Related
This question already has an answer here:
How to deserialize a JSON property that can be two different data types using Json.NET
(1 answer)
Closed 1 year ago.
I have a Json that looks as this:
{
"id": "1367",
"title": "ticket sample",
"custom_fields": {
"13084": {
"E0D4ED43": "South"
},
"13085": {
"F19DF0D6": "Atlanta"
},
"13089": {
"AF0EC62F": "Peter Johnson"
}
}
}
And to parse it, my class uses nested Dictionaries:
class incident
{
public string id { get; set; }
public string title { get; set; }
public Dictionary<int, Dictionary<string, string>> custom_fields { get; set; }
}
This works like a charme, until I've discovered that the custom fields are not always the same, for example I could receive:
{
"id": "1367",
"title": "ticket sample",
"custom_fields": {
"13084": {
"E0D4ED43": "South"
},
"13085": {
"F19DF0D6": "Atlanta"
},
"13086": "SAP",
"13088": {
"AE3ED01A": "Commercial"
}
}
}
If you look at the custom field "13086", it doesn't contains another object (it's just a string), so when I try to parse with the previous class it fails.
Those are examples of two different responses, but the keys received change a lot (that's why I used Dictionaries because I don't know how many and which will be received for each ticket)
Thank you all guys for your comments. Thanks to them I figured it out and found a solution that works for me.
Basically, I've used the "Dictionary<int, object>" proposed by #DilshodK and then I check for the type of the object. If the object is a JObject I re-deserialize with another Dictionary, if not I use the original value.
class incident_custom
{
public string id{ get; set; }
public string title { get; set; }
public Dictionary<int, object> custom_fields { get; set; }
}
incident_custom item = JsonConvert.DeserializeObject<incident_custom>(responseBody);
Console.WriteLine(item.title);
foreach (var field in item.custom_fields)
{
if (field.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
{
Dictionary<string, object> values = JsonConvert.DeserializeObject<Dictionary<string, object>>(field.Value.ToString());
foreach (var value in values)
{
Console.WriteLine(field.Key + " - " + value.Value);
}
}
else
{
Console.WriteLine(field.Key + " - " + field.Value);
}
}
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"
}
}
(Just a heads up, I'm very new to C#)
(See sample code and JSON structure below)
I can't figure out how to pull "data" out of the JSON reponse and put it into a data table. The variable "response" is just raw JSON data. So far I've figured out how to parse the JSON into a JObject...so now it has two members (data, meta). Now I'm trying to figure out how to get joTest["data"] into a DataTable. The handful of attempts I've made, keep giving me an error when it sees the "meta" member. Maybe I shouldn't be using a Data Table?
Also, in case it changes anything, I don't need the "links" from the "data" members.
I've tried searching for "Converting JObject into Data Table" But I'm not finding a lot of useful results.
public void PerformFeed()
{
string response;
response = Blah.SendMessage().Result;
JObject joTest = JsonConvert.DeserializeObject<JObject>(response);
}
Json Data Structure
{
"data": [
{
"Val1": "1234",
"Val2": "foo1",
"Val3": "bar1",
"links": [
{
"rel": "self",
"uri": "/blah/1234"
},
{
"rel": "pricing_data",
"uri": "/blah/1234/pricing_data"
}
]
},
{
"Val1": "5678",
"Val2": "foo2",
"Val3": "bar2",
"links": [
{
"rel": "self",
"uri": "/blah/5678"
},
{
"rel": "pricing_data",
"uri": "/blah/5678/pricing_data"
}
]
}
],
"meta": {
"pagination": {
"total": 2,
"count": 2,
"per_page": 25,
"current_page": 1,
"total_pages": 1,
"links": []
}
}
}
UPDATE: I've figured out a "solution" but I really don't think it's a good solution. I built a datatable and then used a foreach statement on the JObject to populate the data table that way. It seems very inefficient...but for now it works. Hopefully I'll find a better way.
public void PerformFeed()
{
DataTable Items = new DataTable();
Items.Columns.Add("Val1");
Items.Columns.Add("Val2");
Items.Columns.Add("Val3");
string response = Blah.SendMessage().Result;
JObject Data = JObject.Parse(response);
foreach (JObject jo in Data["data"])
{
Items.Rows.Add(jo["Val1"], jo["Val2"], jo["Val3"]);
}
}
There is this really nice online utility that helps extracting C# classes from JSON objects. I think the problem here is with your JSON, you're missing a comma ",". You would easily be able to spot the error with some online JSON formatter / validator. Rest the deserialization is pretty straightforward. Try the following:
JObject obtainedObject = JObject.Parse(JsonString);
Following would be the structure of your obtained object:
public class RequiredClass
{
public IList<Datum> data { get; set; }
public Meta meta { get; set; }
}
public class Datum
{
public string Val1 { get; set; }
public string Val2 { get; set; }
public string Val3 { get; set; }
public IList<Link> links { get; set; }
}
public class Link
{
public string rel { get; set; }
public string uri { get; set; }
}
public class Pagination
{
public int total { get; set; }
public int count { get; set; }
public int per_page { get; set; }
public int current_page { get; set; }
public int total_pages { get; set; }
public IList<object> links { get; set; }
}
public class Meta
{
public Pagination pagination { get; set; }
}
Update:
Here's is how you extract your array and convert that to a DataTable:
JObject jObject = JObject.Parse(json);
JToken dataArray = jObject["data"];
DataTable dt = (DataTable) JsonConvert.DeserializeObject(dataArray.ToString(), (typeof(DataTable)));
To avoid the surplus casting, you can try the following using the class structure already mentioned above:
JObject jObject = JObject.Parse(json);
JToken dataArray = jObject["data"];
List<Datum> requiredList = new List<Datum>();
foreach (var item in dataArray)
{
Datum obj = new Datum();
obj.Val1 = (string) item["Val1"] ?? "";
obj.Val2 = (string) item["Val2"] ?? "";
obj.Val3 = (string) item["Val3"] ?? "";
obj.links = new List<Link>();
foreach(var subItem in item["links"])
{
Link lnk = new Link();
lnk.rel = (string) subItem["rel"] ?? "";
lnk.uri = (string) subItem["uri"] ?? "";
obj.links.Add(lnk);
}
requiredList.Add(obj);
}
I am sending URL request and getting response in curl and then convert into a json...object inside object(contain numeric and dot(924.136028459)) like:
string arr1 =
"{
"success":1,
"results":[
{
"Markets":{
"924.136028459":{
"productType":"BOOK1",
"key":"SB_MARKET:924.136028459"
},
"924.136028500":{
"productType":"BOOK2",
"key":"SB_MARKET:924.136028459"
}
}
}
]
}";
I have created properties class ..but i am not understanding how can we access inside "924.136028500" attributes
public class Json
{
public System.Collections.ObjectModel.Collection<Arr> results { get; set; }
}
public class Arr
{
public sp Markets { get; set; }
}
public class sp
{
public string productType { get; set; }
public string key { get; set; }
}
and I am using deserialize code...
var serializer = new JavaScriptSerializer();
Json json = serializer.Deserialize<Json>(arr1);
With Cinchoo ETL - an open source library, you can load the Market object easily with few lines of code
string json = #"{
""success"":1,
""results"":[
{
""Markets"":{
""924.136028459"":{
""productType"":""BOOK1"",
""key"":""SB_MARKET:924.136028459""
},
""924.136028500"":{
""productType"":""BOOK2"",
""key"":""SB_MARKET:924.136028459""
}
}
}
]
}
";
foreach (var rec in ChoJSONReader<sp>.LoadText(json).WithJSONPath("$..Markets.*"))
Console.WriteLine($"ProductType: {rec.productType}, Key: {rec.key}");
Output:
ProductType: BOOK1, Key: SB_MARKET:924.136028459
ProductType: BOOK2, Key: SB_MARKET:924.136028459
Checkout CodeProject article for some additional help.
Disclaimer: I'm the author of this library.
I need to parse this JSON String to my object of type "WeatherJson". However I do not know how to parse the arrays inside the string such as '"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}]. What would the entity class look like?
The JSON String:
{
"coord": {"lon":79.85,"lat":6.93},
"sys": {
"type": 1,
"id": 7864,
"message": 0.0145,
"country": "LK",
"sunrise": 1435883361,
"sunset": 1435928421
},
"weather": [
{"id":802, "main":"Clouds", "description":"scattered clouds", "icon":"03d"}
],
"base": "stations",
"main": {
"temp": 302.15,
"pressure": 1013,
"humidity": 79,
"temp_min": 302.15,
"temp_max": 302.15
},
"visibility":10000,
"wind": { "speed": 4.1, "deg": 220 },
"clouds": { "all": 40 },
"dt": 1435893000,
"id":1248991,
"name":"Colombo",
"cod":200
}
EDIT
I need to retrieve following values from the code:
WeatherJson w = new WeatherJson();
Console.WriteLine(w.weather.description);
//that above line was retrieved and stored from the JSONArray named 'weather' in the main json response
You should just make the arrays in the JSON match with list or array types in your POCO. Here's a short but complete example using the JSON you've provided:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
class Test
{
static void Main(string[] args)
{
var json = File.ReadAllText("weather.json");
var root = JsonConvert.DeserializeObject<Root>(json);
Console.WriteLine(root.Weather[0].Description);
}
}
public class Root
{
// Just a few of the properties
public Coord Coord { get; set; }
public List<Weather> Weather { get; set; }
public int Visibility { get; set; }
public string Name { get; set; }
}
public class Weather
{
public int Id { get; set; }
public string Description { get; set; }
}
public class Coord
{
public double Lon { get; set; }
public double Lat { get; set; }
}
Try like this:
void Main()
{
var json = System.IO.File.ReadAllText(#"d:\test.json");
var objects = JArray.Parse(json); // parse as array
foreach(JObject root in objects)
{
foreach(KeyValuePair<String, JToken> app in root)
{
var appName = app.Key;
var description = (String)app.Value["Description"];
var value = (String)app.Value["Value"];
Console.WriteLine(appName);
Console.WriteLine(description);
Console.WriteLine(value);
Console.WriteLine("\n");
}
}
}
Try this hope it will help you....
var dataObj=JSON.parse {"coord":{"lon":79.85,"lat":6.93},"sys":
{"type":1,"id":7864,"message":0.0145,"country":"LK",
"sunrise":1435883361,
"sun set":1435928421},"weather": [{"id":802,"main":"Clouds",
"description":"scattered clouds","icon":"03d"}],
"base":"stations","main":{"temp":302.15,"pressure":1013,
"humidity":79,"temp_min":302.15,
"temp_max":302.15},"visibility":10000,"wind":{"speed":4.1,"deg":220},
"clouds":{"all":40},"dt":1435893000,"id":1248991,
"name":"Colombo","cod":200}
to read this .
i m reading one single string so u can able to know.
var windData=dataObj.wind.speed;
it will read value 4.1 from your string like this..
If u want to read array of string then..
var weatherObj=dataObj.weather[0].description;
so it will read description value from array.like this u can read.
Try double iteration,
for (key in parent) {
for(key1 in parent[key]){
//
}
}
JObject defines method Parse for this:
JObject json = JObject.Parse(JsonString);
You might want to refer to Json.NET documentation.
If you have collection of object then you can use JArray
JArray jarr = JArray.Parse(JsonString);
For documentation you can see here.
To Convert JArry to List Just put below method. It will return what you need.
Jarray.ToObject<List<SelectableEnumItem>>()
You can use JavaScriptSerializer Class to parse the JSON to Object.
Refer this StackOverflow thread