How to deserialize json of this kind into an object on C# ?
{
"AND":[
{
"AND":[
{
"AND":[
{
"AND":[
{
"AND":[
{
"AND":[
{
"OR":[
{
"OR":[
"Title",
"Login"
]
},
"LoginNote"
]
},
"BossTitle"
]
},
{
"OR":[
"Phone",
"TeleGorod"
]
}
]
},
"Room"
]
},
"Division"
]
},
"TabelnyiNomer"
]
},
"Filter\""
]
}
You can play with dynamic type, but I don't think it can help you.
class Program
{
static void Main(string[] args)
{
string unknownJson1 = "{\r\n \"Id\": \"1e4495d3-4cd1-4bf2-9da6-4acee2f7a70e\",\r\n \"Customers\": [\r\n \"Alice\",\r\n \"Bob\",\r\n \"Eva\"\r\n ]\r\n}";
string unknownJson2 = "{\"AND\": [\"_ x041f__x0435__x0440__x0432__x04\", {\"AND\": [\"_ x0418__x0437__x0433__x043e__x04\", {\"AND\": [\"_ x041e__x043f__x0438__x0441__x04\", {\"AND\": [\"_ x041a__x043e__x0434_\", \"Title\"]}]}]}] } ";
JsonSerializer serializer = new JsonSerializer();
dynamic deserializedObject;
using (var stringReader = new StringReader(unknownJson2))
{
using (var jsonReader = new JsonTextReader(stringReader))
{
deserializedObject = serializer.Deserialize(jsonReader);
}
}
Console.ReadKey(true);
}
}
quicktype's CLI supports JSON schema as an import format, which could help you represent the tree data structure you're parsing here. I'll look into why it wasn't detected automatically, but here's your model:
public class Tree
{
[JsonProperty("AND")]
public Leaf[] And { get; set; } // Could be null
[JsonProperty("OR")]
public Leaf[] Or { get; set; } // Could be null
}
public struct Leaf
{
public string String; // Could be null
public Top Tree; // Could be null
}
Your JSON should parse as this, although I haven't tested it.
Related
I have a JSON being received from a public API that follows the structure below.
[
{
"ID": "12345",
"company": [
{
"contract_ID": "abc5678",
"company": [
{
"company_name": "HelloWorld",
"company_logo": "HW",
"invested": "2000"
}
]
},
{
"contract_ID": "67891",
"company": [
{
"company_name": "GoodBye",
"company_logo": "GB",
"invested": "500"
}
]
},
{
"contract_ID": "32658",
"company": [
{
"company_name": "YesNo",
"company_logo": "YN",
"invested": "1500"
}
]
}
]
}
]
I've tried several different methods of parsing, whether it be JTokens/JArrays or various classes. Something like the following allows me to access the first group of values (company_name, company_logo, invested), but I cannot iterate through to find the other two.
//receiving the json data
var responseString = await response.Content.ReadAsStringAsync();
var fullJSON = JsonConvert.DeserializeObject(responseString);
Debug.Log(fullJSON);
//trying to parse it down to just the data I need
JToken token = JToken.Parse("{\"root\":" + responseString + "}");
Debug.Log(token);
JArray assets = (JArray)token.SelectToken("root[0].assets");
Debug.Log(assets);
JToken dig = JToken.Parse("{\"root\":" + assets + "}");
Debug.Log(dig);
JArray assetsNested = (JArray)dig.SelectToken("root[0].assets");
Debug.Log(assetsNested);
My goal is to extract the contract_ID and then the associated company_name, company_logo, and invested items. For example, abc5678, HelloWorld, HW, and 2000 would be one of the three datasets needed.
The easiest way to deserialize this properly and keep your code maintainable is to use concrete classes. For example:
public sealed class Company
{
[JsonProperty("contract_ID")]
public string ContractID { get; set; }
[JsonProperty("company")]
public List<CompanyDefinition> CompanyDefinitions { get; set; }
}
public sealed class CompanyDefinition
{
[JsonProperty("company_name")]
public string CompanyName { get; set; }
[JsonProperty("company_logo")]
public string CompanyLogo { get; set; }
[JsonProperty("invested")]
public string Invested { get; set; }
}
public sealed class RootCompany
{
[JsonProperty("ID")]
public string ID { get; set; }
[JsonProperty("company")]
public List<Company> Company { get; set; }
}
Then, you simply deserialize. For example, if you are pulling from a file you could do this:
using(var sr = new StreamReader(#"c:\path\to\json.json"))
using(var jtr = new JsonTextReader(sr))
{
var result = new JsonSerializer().Deserialize<RootCompany[]>(jtr);
foreach(var r in result)
{
Console.WriteLine($"Company ID: {r.ID}");
foreach(var c in r.Company)
{
Console.WriteLine($"ContractID: {c.ContractID}");
foreach(var d in c.CompanyDefinitions)
{
Console.WriteLine($"Name: {d.CompanyName}");
Console.WriteLine($"Invested: {d.Invested}");
Console.WriteLine($"Company Logo: {d.CompanyLogo}");
}
}
}
}
When something changes with your models, you won't have to dig through lines upon lines of hard-to-read token selection code. You just update your models.
I have a situation while working with a JSON response from an API. To give a background, I am consuming an API from a source using a REST API using 3.5 .net framework.
Below is the part of the JSON output and I am kind of struggling to use it.
a)
"value": {
"Description": "Total Calculated things",
"2018": "5,820,456 ",
"2019": "2,957,447 "
}
The last 2 elements are dynamic, those are tend to change in API response. I was expecting the format like I have mentioned below, but at this point of given time the source provider is not able to change it as the API is used in many other different programs. And Changing the things in the source API will make other program owners to change.
b)
"value": {
"Description": "Total Calculated EQUITY AND LIABILITIES",
"YearData": [ {
"Data": "5,820,456",
"Year": "2018"
},
{
"Data": "2,957,447 ",
"Year": "2019"
} ]
}
Is there any way to overcome such thing> Any way to convert a to b?
EDIT
#Xerillio , Thanks . How can I achieve the same using below JSON format.
var json = #"
{
""entityData"": [
{
""name"": ""Statement of Comprehensive Income"",
""subattrOutput"": [
{
""name"": ""Sales"",
""subattrOutput"": [],
""value"": {
""Description"": ""Sales "",
""2018"": ""8,704,888 "",
""2019"": ""4,760,717 ""
},
""score"": ""99.5"",
""valuetype"": ""object""
},
{
""name"": ""Cost of goods sold"",
""subattrOutput"": [],
""value"": {
""Description"": ""Cost of sales "",
""2018"": ""(6,791,489) "",
""2019"": ""(3,502,785) ""
},
""score"": ""99.75"",
""valuetype"": ""object""
}
],
""value"": null,
""score"": ""98.63"",
""valuetype"": ""object""
}
]
}";
I wish this was more easy, but i just got it here:
class Program
{
static async Task Main(string[] args)
{
string json1 = #"{""value"": {""Description"": ""Total Calculated things"",""2018"": ""5,820,456 "",""2019"": ""2,957,447 ""}}";
string json2 = #"{""value"": {""Description"": ""Total Calculated EQUITY AND LIABILITIES"",""YearData"": [ {""Data"": ""5,820,456"",""Year"": ""2018""},{""Data"": ""2,957,447 "",""Year"": ""2019""} ]}}";
var obj1 = JsonConvert.DeserializeObject<ObjectResult>(json1);
var obj2 = JsonConvert.DeserializeObject<ObjectResult>(json2);
var res1 = CastObject<Result1>(obj1.Value.ToString());
var res2 = CastObject<Result2>(obj2.Value.ToString());
var invalidRes1 = CastObject<Result1>(obj2.Value.ToString());
var invalidRes2 = CastObject<Result2>(obj1.Value.ToString());
Console.WriteLine(res1);
Console.WriteLine(res2);
}
public static T CastObject<T>(string obj)
{
return !TryCastObject(obj, out T result) ? default : result;
}
public static bool TryCastObject<TOut>(string objToCast, out TOut obj)
{
try
{
obj = JsonConvert.DeserializeObject<TOut>(objToCast);
return true;
}
catch
{
obj = default;
return false;
}
}
}
public class ObjectResult
{
public object Value { get; set; }
}
public class Result1
{
[JsonProperty(PropertyName = "description")] public string Description { get; set; }
[JsonProperty(PropertyName = "2018")] public string _2018 { get; set; }
[JsonProperty(PropertyName = "2019")] public string _2019 { get; set; }
}
public class Result2
{
[JsonProperty(PropertyName = "Description")] public string Description { get; set; }
[JsonProperty(PropertyName = "YearData")] public List<YearData> YearData { get; set; }
}
public class YearData
{
[JsonProperty(PropertyName = "Data")] public string Data { get; set; }
[JsonProperty(PropertyName = "Year")] public string Year { get; set; }
}
It is A LOT of work and sincerely, as there more nodes in the json i think that using JObject is the best option, and you will have to do a deserealization in more than 1 step :(
Depending on how large the JSON structure is you could deserialize it into a Dictionary and manually map it to the proper format:
var json = #"
{
""value"": {
""Description"": ""Total Calculated things"",
""2018"": ""5,820,456 "",
""2019"": ""2,957,447 ""
}
}";
var badObj = JsonSerializer.Deserialize<BadFormat>(json);
var result = new WrapperType
{
Value = new ProperlyFormattedType()
};
foreach (var pair in badObj.Value)
{
if (pair.Key == "Description")
{
result.Value.Description = pair.Value;
}
else if (int.TryParse(pair.Key, out int _))
{
result.Value.YearData
.Add(new DatedValues
{
Year = pair.Key,
Data = pair.Value
});
}
}
// Data models...
public class BadFormat
{
[JsonPropertyName("value")]
public Dictionary<string, string> Value { get; set; }
}
public class WrapperType
{
public ProperlyFormattedType Value { get; set; }
}
public class ProperlyFormattedType
{
public string Description { get; set; }
public List<DatedValues> YearData { get; set; } = new List<DatedValues>();
}
public class DatedValues
{
public string Year { get; set; }
public string Data { get; set; }
}
See an example fiddle here.
I am having a string in the following format. I want to assign each JSON within the projects to a separate JObject. When I am trying to parse it and assign accordingly, I am unable to achieve it. How can I parse it?
{
"projects": [
{
"sno": "1",
"project_name": "Abs",
"project_Status": "Live"
},
{
"sno": "2",
"project_name": "Cgi",
"project_Status": "Live"
}
]
}
I have tried the following code;
using (StreamReader streamReader = new StreamReader(Path.Combine(Path.GetTempPath(), "sample.json")))
using (JsonTextReader reader = new JsonTextReader(streamReader))
{
var serializer = new JsonSerializer();
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
JObject jsonPayload = JObject.Load(reader);
jsonProfile = jsonPayload.ToString();
JObject json = JObject.Parse(jsonProfile);
}
}
}
you can use DeserializeAnonymousType as a simpler solution to parse json.
var definition = new
{
projects = new[]{
new {
sno="1",
project_name= "Abs",
project_Status= "Live"
}
}
};
string json1 = #" {
'projects': [
{
'sno': '1',
'project_name': 'Abs',
'project_Status': 'Live'
},
{
'sno': '2',
'project_name': 'Cgi',
'project_Status': 'Live'
}
]
}";
var projects = JsonConvert.DeserializeAnonymousType(json1, definition);
but if you do want to use strong type, you'd better to use JsonProperty
public class Project
{
[JsonProperty("sno")]
public string Sno { get; set; }
[JsonProperty("project_name")]
public string ProjectName { get; set; }
[JsonProperty("project_Status")]
public string ProjectStatus { get; set; }
}
public class JsonModel
{
[JsonProperty("Projects")]
public List<Project> projects { get; set; }
}
JsonConvert.DeserializeObject<JsonModel>(json_Data);
I am currently consuming JSON output from one source that contains an array and one that does not.
The one with an array is simple, as I can create a class that represents the object and the list of objects, then iterate through the list and get the properties for each object. In the source that does not have an array, however, it is throwing me for a loop.
I do not know how to iterate through this. It seems as if I would need to create separate classes for "abc" and "def" even though the properties of each class are the same. Is there a simple way to do this?
Example that does not contain an array:
{
"objectContainer": {
"count": 25,
"objects": {
"abc": {
"name": "object1",
"parent": "0",
"status": "0",
},
"def": {
"name": "object2",
"parent": "0",
"status": "0",
}
etc....
Thanks in advance for any assistance.
You could use inheritance to prevent repeating the properties for "abc" and "def" over and over again.
public class Base
{
public string name { get; set; }
public string parent { get; set; }
public string status { get; set; }
}
public class Abc : Base { }
public class Def : Base { }
public class Objects
{
public Abc abc { get; set; }
public Def def { get; set; }
}
public class ObjectContainer
{
public int count { get; set; }
public Objects objects { get; set; }
}
public class RootObject
{
public ObjectContainer objectContainer { get; set; }
}
Then using JSON.NET you can deserialize the string.
var root = JsonConvert.DeserializeObject<RootObject>( json );
The problem is you're going to have to change the code every time you get a new object in there (e.g. ghi).
Another option, particularly if you're going to have different object names showing up, would be to just parse the JSON serially yourself.
JsonTextReader reader = new JsonTextReader( new StringReader( json ) );
while( reader.Read() )
{
if( reader.Value != null )
{
Console.WriteLine( "Field: {0}, Value: {1}", reader.TokenType, reader.Value );
}
}
Obviously where it's writing output to the Console you'd have to examine the TokenType and Value and stuff those into an object.
Update
This is pretty ugly, but I was curious how I might parse this into the object structure. You'd need to change the receiving object definitions a bit.
public class Base
{
public string name { get; set; }
public string parent { get; set; }
public string status { get; set; }
}
public class Objects
{
public List<Base> bases { get; set; }
public Objects()
{
bases = new List<Base>();
}
}
public class ObjectContainer
{
public int count { get; set; }
public Objects objects { get; set; }
public ObjectContainer()
{
objects = new Objects();
}
}
public class RootObject
{
public ObjectContainer objectContainer { get; set; }
public RootObject()
{
objectContainer = new ObjectContainer();
}
}
Then you can parse into it using:
while( reader.Read() )
{
if( reader.Value != null )
{
switch( reader.Depth )
{
case 2:
if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "count" )
{
reader.Read();
root.objectContainer.count = Convert.ToInt32( reader.Value );
}
break;
case 3:
newBase = new Base();
root.objectContainer.objects.bases.Add( newBase );
break;
case 4:
if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "name" )
{
reader.Read();
newBase.name = reader.Value.ToString();
}
if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "parent" )
{
reader.Read();
newBase.parent = reader.Value.ToString();
}
if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "status" )
{
reader.Read();
newBase.status = reader.Value.ToString();
}
break;
}
}
}
Not the prettiest code in the world but as long as the structure of the JSON doesn't change you'll end up with a nice object model no matter how many child objects or what their names are.
Based on your JSON above, you would probably need to create classes for those objects. You can abstract some of it away with inheritance as well. If possible, it would make more sense for "objects" to be an array that way you don't need to create separate objects. The name, and implementation both suggest an array.
If you cannot change the structure of the JSON, have a look at the bottom of the page at http://json.org/ for different libraries. Some may be more helpful than others. Json.NET is the one I usually use and you may have better results using something like their JSonReader so you don't have to create an overly complex object structure.
You could use the excellent (and dynamic) JObject class from the JSON.NET library like this:
// example input
var json = #"{""objectContainer"": {
""count"": 25,
""objects"": {
""abc"": {
""name"": ""object1"",
""parent"": ""0"",
""status"": ""0"",
},
""def"": {
""name"": ""object2"",
""parent"": ""0"",
""status"": ""0"",
}
}}";
var obj = JsonConvert.DeserializeObject(json);
var objectContainer = ((JObject)obj)["objectContainer"];
var abc = objectContainer["objects"]["abc"];
Console.WriteLine(abc["name"]);
The output is:
output1
You could even use directly the JObject.Parse() method to load and parse just a JSON code portion (for example if you can extract only the abc part from the complete JSON string):
var abc = JObject.Parse(#"{""abc"": {
""name"": ""object1"",
""parent"": ""0"",
""status"": ""0"",
}}")["abc"];
Console.WriteLine(abc["name"]);
var abcd = JObject.Parse(#"{
""name"": ""object1"",
""parent"": ""0"",
""status"": ""0"",
}");
Console.WriteLine(abcd["name"]);
You could then assign the extracted values to your custom class.
Using the library and the JObject class you don't need to represent the JSON with a class. The downside is, that you don't have the type safety of the class and it's properties.
Update
You could iterate over the properties / objects without knowing their names:
var obj = JsonConvert.DeserializeObject(json);
var objectContainer = ((JObject)obj)["objectContainer"];
foreach (var o in objectContainer["objects"])
{
if (o is JProperty)
{
var op = ((JProperty)o);
Console.WriteLine("{0} - {1}", op.Name, op.Value);
}
}
The output is:
abc - {
"name": "object1",
"parent": "0",
"status": "0"
}
def - {
"name": "object2",
"parent": "0",
"status": "0"
}
I have Called a Json Web Service and got the result in c#.The Json Web service data is available in format:
{
"Count": 9862,
"Items": [
{
"Admin": {
"S": "false"
},
"UserId": {
"S": "e9633477-978e-4956-ab34-cc4b8bbe4adf"
},
"Age": {
"N": "76.24807963806055"
},
"Promoted": {
"S": "true"
},
"UserName": {
"S": "e9633477"
},
"Registered": {
"S": "true"
}
},
{
"Admin": {
"S": "false"
},
"UserId": {
"S": "acf3eff7-36d6-4c3f-81dd-76f3a8071bcf"
},
"Age": {
"N": "64.79224276370684"
},
"Promoted": {
"S": "true"
},
"UserName": {
"S": "acf3eff7"
},
"Registered": {
"S": "true"
}
},
I have got the Response like this in c#:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8000/userdetails");
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
after finally successfully get the response i have got all the Data in string. and then parse this string in list of objects .Now I have list of objects where it showing the count in debugging.Now I want to access the values like UserId:acf3eff7-36d6-4c3f-81dd-76f3a8071bcf like properties.I dont know how to do it.Please help me and any help will be appreciated.
You can use the following code to get the values from json as:
JObject obj = JObject.Parse(json);
int count = (int)obj["Count"];
var Items = obj["Items"];
foreach (var item in Items)
var admin = item["Admin"];
Quick and dirty way:
//deserialize your string json using json.net
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
//get value of UserId in first Item
var UserId = jsonObj["Items"][0]["UserId"]["S"];
//OR get the value of UserId for each Item in Items
//foreach(dynamic item in jsonObj["Items"])
//item["UserId"]["S"];
Advice is to use c# objects as mentioned by #yousuf
To be able to access Json property like common C# object property, you need to deserialize json string to strongly typed object (you can use, for example, JSON.NET to do deserialization).
Another handy tool is http://json2csharp.com/. Paste your Json there then you can generate classes definitions that suitable to map the Json automatically :
//RootObject class definition generated using json2csharp.com
//the rest of class definition removed for brevity.
public class RootObject
{
public int Count { get; set; }
public List<Item> Items { get; set; }
}
........
........
//in main method
var jsonString = .....;
//deserialize json to strongly-typed object
RootObject result = JsonConvert.DeserializeObject<RootObject>(jsonString);
foreach(var item in result.Items)
{
//then you can access Json property like common object property
Console.WriteLine(item.UserId.S);
}
you are deserializing string to c# object. you will need to create object that reperesents the json .
For example -
public class Admin
{
public string S { get; set; }
}
public class UserId
{
public string S { get; set; }
}
public class Age
{
public string N { get; set; }
}
public class Promoted
{
public string S { get; set; }
}
public class UserName
{
public string S { get; set; }
}
public class Registered
{
public string S { get; set; }
}
public class RootObject
{
public Admin Admin { get; set; }
public UserId UserId { get; set; }
public Age Age { get; set; }
public Promoted Promoted { get; set; }
public UserName UserName { get; set; }
public Registered Registered { get; set; }
}
Then deserialize json string to object using jsonSerializer
JavaScriptSerializer serializer = new JavaScriptSerializer();
var result =
(RootObject)serializer .DeserializeObject("Json String")
string json = #"{
""Name"": ""Apple"",
""Expiry"": new Date(1230422400000),
""Price"": 3.99,
""Sizes"": [
""Small"",
""Medium"",
""Large""
]
}";
JObject o = JObject.Parse(json);
//This will be "Apple"
string name = (string)o["Name"];