Reading dynamic attributes of json into .net C# - c#

I am getting following json format after hitting to an API:
{
"7407": {
"survey_id": "406",
"device_id": "1",
"response_time": "2013-10-10 16:14:01",
"timezone": "0",
"language_id": "en",
"response_id": "7407",
"device_alias": "QR Code App",
"site_name": "QR Code App",
"country_name": "United States",
"state_name": "New York",
"city_name": "Suffern",
"zip": "",
"voucher_name": null,
"voucher_mode": null,
"surveyee_name": null,
"surveyee_email": null,
"surveyee_phone": null,
"ques": {
"": []
}
},
"7408": {
"survey_id": "406",
"device_id": "1",
"response_time": "2013-10-10 16:36:56",
"timezone": "0",
"language_id": "en",
"response_id": "7408",
"device_alias": "QR Code App",
"site_name": "QR Code App",
"country_name": "India",
"state_name": "Gujarat",
"city_name": "Ahmedabad",
"zip": "",
"voucher_name": null,
"voucher_mode": null,
"surveyee_name": null,
"surveyee_email": null,
"surveyee_phone": null,
"ques": {
"": []
}
} }
I am using JSON.Net to read the above given json data.
To map this data into .Net code, I will need classes in .net, having same properties' name as in json string.
BUT there are some attributes in json which can be dynamic ("7407", "7408" etc in my case) i.e. this value can be changed based on what are we passing into parameters.
My question is, how can we map json attributes (which are dynamic in nature and can have any value depending upon the parameters provided to the apis) to our .net class ?

You could map it to a Dictionary. Where your dynamic property is the Key of a DictionaryIem and the Objet is the Value of your DictionaryItem.
For Exmaple:
public class MyClass
{
public void readJson)
{
var json = "{\"7407\": {\"survey_id\": \"406\",\"device_id\": \"1\",},\"7408\": {\"survey_id\": \"406\",\"device_id\": \"1\",}}";
Dictionary<int, MyObject> dict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<int, MyObject>>(json);
var count = dict.Keys.Count;
}
}
public class MyObject
{
public string survey_id { get; set; }
public string device_id { get; set; }
}
For this exmaple i simplified your json. so that it looks like this:
{
"7407": {
"survey_id": "406",
"device_id": "1"
},
"7408": {
"survey_id": "406",
"device_id": "1"
}
}

Js object is a dictionary, so you can map to Dictionary with key = some attribute, and value - .Net code what you want
Dictionary<object,'your data class'>

The best way I could find handling this kind of JSON data is by using JObject class of the JSON.Net library.
For eg:
Newtonsoft.Json.Linq.JObject jSonObject = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(somejsonstring);
and then you can loop through or apply some other logic to read jSonObject

Related

How can I access my nested data using variables C#

I have a json file and I deserialised it as shown in the code below. Some context, dex is a robot and it has information such as battery and so on as shown in the json file below. I want to read the battery status for the robot that the user selected ( robot).
This is my code, currently im only accessing data.dex but i want to change it to whichever data.robot, where robot is a variable
var data = JsonConvert.DeserializeObject<Root>(json);
var robot = queryDetails2.Amr;
var text =$"";
if (data.dex.battery.status == "good")
{
text = $"{queryDetails2.Amr}'s battery is in good condition. ";
}
This is the json file:
{
"dex":
{
"current_job":
{"job":null, "task": null, "location": null},
"battery":
{"name":"battery", "status": "good", "value": "100"},
},
"dex_1":
{
"current_job":
{"job":null, "task": null, "location": null},
"battery":
{"name":"battery", "status": "good", "value": "100"},
},
"dex_2":
{
"current_job":
{"job":null, "task": null, "location": null},
"battery":
{"name":"battery", "status": "good", "value": "100"},
}
}
I wanted to use the GetMethod or the solution as suggested in this question (https://stackoverflow.com/questions/53076743/how-to-access-variable-of-a-nested-functions-in-python[1]).
However, im getting errors like it does not have a method. Now im confused, was it because i used var? but the deserialised method converts the json to an object though..
Anyway, how should i approach this?
Assuming that you have 3 robots with different names: dex, dex_1 and dex_2, you should reorganize your solution to treat the json data as a list of Robots instead of 3 separate variables for each robot.
To do this, first your json should look like this:
{
"robots":[
{
"name":"dex",
"current_job":{
"job":null,
"task":null,
"location":null
},
"battery":{
"name":"battery",
"status":"good",
"value":"100"
}
},
{
"name":"dex_1",
"current_job":{
"job":null,
"task":null,
"location":null
},
"battery":{
"name":"battery",
"status":"good",
"value":"100"
}
},
{
"name":"dex_2",
"current_job":{
"job":null,
"task":null,
"location":null
},
"battery":{
"name":"battery",
"status":"good",
"value":"100"
}
}]
}
Next, update your serialization classes. Add a field called name in the Robot class or whatever class type you currently have for data.dex. In Root, remove the "dex" fields and add a List<Robot>.
public class Root
{
public List<Robot> robots { get; set; }
}
public class Robot
{
public string name { get; set; }
public Job current_job { get; set;}
public Battery battery{ get; set; }
}
Now you can write whatever logic to get the right robot data. Here is an example using System.Linq:
var robotName = "dex_2";
var robotInfo = data.robots.First(x => x.name.Equals(robotName));
var text = $"{robotName}'s battery is in {robotInfo.battery.status} condition.";

How can I map REST entities with my own models

I have been given a REST service which provides some strange names, see json fomart below.
I have created some classes to map them to JSON using the following line:
var data = JsonConvert.DeserializeObject<SSTR)(jsond).inhoud_b.ToArray();
I have created classes such as:
Class inhoud_b {...}
Class bidt{...}
etc.
Json:
{
"nmbr": 0,
"tp": 1,
"sort": {
"sorted": false,
"unsorted": true
},
"inhoud_b":[
{
"bidt": {
"id": "144a207b-dd48-4ebe-87cb-153e3c6179c4",
"knldge": null,
"lTT": null,
"lD": {
"id": "52",
"text": "EM"
}
}
},
{
"bidt": {
"id": "155B307b-dd48-4ebe-87cb-125487856579",
"knldge": null,
"lTT": null,
"lDg": {
"id": "523",
"text": "AM"
}
}
}
],
"first": true,
"totalElements": 2
}
My question is, how can I map these entities with my own more meaningful models and use my models in my own code rather than those entities which don't make any sense to other developers?
Thank you.
You can use the JsonPropertyAttribute to annotate your model properties with their corresponding property name in the JSON - https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm

In C#, how can i deserialize this json?

I am getting this JSON data back from a REST service that looks like this:
[ [ [ {"Name": "Joe", "Comment": "Load", "Updated": null, "Test": ""} ] ] ]
or
[ [ [ {"Name": "Joe", "Comment": "Load", "Updated": null, "Test": ""}, {"Name": "Bill", "Comment": "123", "Updated": null, "Test": ""} ] ] ]
I did a "Copy JSON as classes" feature in visual studio and it created this:
public class Rootobject
{
public Project[][][] Property1 { get; set; }
}
public class Project
{
public string Name { get; set; }
public string Comment { get; set; }
public string Updated { get; set; }
public string Test { get; set; }
}
but when i try to deserialize using this code:
var results = new JsonDeserializer().Deserialize<Rootobject>(response);
I get an error stating:
An exception of type 'System.InvalidCastException' occurred in RestSharp.dll but was not handled in user code
Additional information: Unable to cast object of type 'RestSharp.JsonArray' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'
Could you please advise on what I might be doing wrong (NOTE: i don't have any control over how the data comes in so changing the format isn't an option)
Also, to confirm this seems to be valid JSON from JSONLlint:
Using Newtonsoft.Json nuget package,
try
JSONConvert.DeserialiseObject<Rootobject>(response)
EDIT: BTW, I tried to use your json on http://json2csharp.com/ and it says Parsing your JSON didn't work. Please make sure it's valid. So I doubt that any json parsing library will be able to parse your JSON.
However implementing your own deserializer is possible and an ideal solution when external services return invalid JSON
I can probably help you deserialize it if you show me what JSON you get when service returns multiple Project objects.
EDIT2: Szabolcs's solutions seems promising, but I would still suggest testing it with JSON for multiple Product objects. I smell something bad & its the shitty third party service. Always good to test.
You can deserialize that particular JSON like this using Json.NET:
var json = "[ [ [ {\"Name\": \"Joe\", \"Comment\": \"Load\", \"Updated\": null, \"Test\": \"\"}, "+
" {\"Name\": \"Bill\", \"Comment\": \"123\", \"Updated\": null, \"Test\": \"\"} ] ] ]";
var deserializedObject = JsonConvert.DeserializeObject<List<List<List<Project>>>>(json);
And to get all the Projects from the nested lists:
var allProjects = deserializedObject.SelectMany(x => x.SelectMany(y => y)).ToList();

retrieve item from a json file c#

{
"_id": "underscore",
"_rev": "136-824a0ef7436f808755f0712c3acc825f",
"name": "underscore",
"description": "JavaScript's functional programming helper library.",
"dist-tags": {},
"versions": {
"1.0.3": {
"name": "xxx",
"description": "xxx"
},
"1.0.4": {},
"1.1.0": {}
}
}
I would like to retrieve the latest version(1.1.0) from the json file. However, it always gives out me errors of "can not deserialize json object into type RootObject
Here is my class
public class versions
{
public string name { get; set; }
public string description { get; set; }
}
public class RootObject
{
public List<versions> vs { get; set; }
}
And here is where I used it
RootObject[] dataset = JsonConvert.DeserializeObject<RootObject[]>(json);
Any idea. Many thankx
Update:
I have updated the JSON file format, but some problem..
I think the problem is, that in JSON you have to quote all "field"/attribute names. (Thats a difference from standard Javascript-Notation, where you can have unquoted attributes).
So, your file should be like:
{
"_id" : "underscore",
"versions": {
"1.0.3" : {
"name": "xxx",
"description": "xxx"
}
}
Note that {1.0.3: { name: "xxx" } } wouldn't be valid JavaScript either since '1.0.3' is an invalid identifier in JavaScript.
Looking at the JSON in your updated answer:
{
"_id" : "underscore",
"versions": {
"1.0.3" : {
"name": "xxx",
"description": "xxx"
},
"1.0.4" : {
"name": "xxx",
"description": "xxx"
}
}
This is still Invalid JSON - you have 4 opening { and only 3 closing }
you should use http://jsonlint.com/ - to validate your JSON and ensure it is Valid
I've fixed your json in question. Now for your real question
I would like to retrieve the latest version(1.1.0) from the json file. However, it always gives out me errors of "can not deserialize json object into type RootObject
You have property names like 1.0.3 that are unknown at compile time. So you can not deserialize them to a concrete class. You should handle them dynamically.
Try this:
var versions = JObject.Parse(json)["versions"]
.Children()
.Cast<JProperty>()
.ToDictionary(c => c.Name, c => c.Value.ToObject<versions>());

Simple JSON deserializaiton

I know this is not hard, but I've been staring at the JSON.Net documentation for a half hour and don't see how it works. I've got it setup, but my initial attempts are failing and the documenation that I have looked at so far isn't making it obvious (to me, at least) how to deserialize the array form response.data and then get at the individual fields of each record.
Also, I don't need to use JSON.Net - it just seemed like a good choice. Any solution will do just fine.
{
"request":{
"Format":"json",
"Target":"Affiliate",
"Method":"findAll",
"Service":"HasOffers",
"Version":"2",
"NetworkId":"directagents",
"NetworkToken":"......"
},
"response":{
"status":1,
"data":{
"2056":{
"Affiliate":{
"id":"2056",
"company":
"123 Greetings 123 Greetings (CD186)",
"address1":"1 Change Address",
"address2":"",
"city":"City",
"region":"NY",
"country":"US",
"other":null,
"zipcode":"11111",
"phone":"-",
"fax":null,
"website":null,
"signup_ip":null,
"date_added":"2012-02-24 18:00:24",
"modified":-62169966000,
"ref_id":"CD186",
"status":"pending",
"wants_alerts":"1",
"account_manager_id":"20",
"payment_method":"check",
"payment_terms":"net 30",
"w9_filed":"0",
"referral_id":null,
"affiliate_tier_id":null,
"fraud_activity_score":null,
"fraud_activity_alert_threshold":null,
"fraud_activity_block_threshold":null,
"fraud_profile_alert_threshold":null,
"fraud_profile_block_threshold":null,
"scrub_offer_pixels":null,
"shared":"0"
}
},
"1606":{
.......this is enough to see how its structured....
You could model that “array” as Dictionary<int, AffiliateHolder>. The classes for that JSON could look like this:
class Top
{
public Request Request { get; set; }
public Response Response { get; set; }
}
class Request
{
public string Format { get;set; }
// etc.
}
class Response
{
public int Status { get; set; }
public Dictionary<int, AffiliateHolder> Data { get; set; }
}
class AffiliateHolder
{
public Affiliate Affiliate { get; set; }
}
class Affiliate
{
public int Id { get; set; }
// etc.
}
var o = JsonConvert.DeserializeObject<Top>(myJSONString);
The fastest, easiest way is to use Json.NET and LINQ to Json. Given your example above, the following code:
var parsedJson = JObject.Parse(rawJson);
foreach (var item in parsedJson["response"]["data"])
{
Console.WriteLine(item.ToString());
}
would write out the following to the console:
"2056": {
"Affiliate": {
"id": "2056",
"company": "123 Greetings 123 Greetings (CD186)",
"address1": "1 Change Address",
"address2": "",
"city": "City",
"region": "NY",
"country": "US",
"other": null,
"zipcode": "11111",
"phone": "-",
"fax": null,
"website": null,
"signup_ip": null,
"date_added": "2012-02-24 18:00:24",
"modified": -62169966000,
"ref_id": "CD186",
"status": "pending",
"wants_alerts": "1",
"account_manager_id": "20",
"payment_method": "check",
"payment_terms": "net 30",
"w9_filed": "0",
"referral_id": null,
"affiliate_tier_id": null,
"fraud_activity_score": null,
"fraud_activity_alert_threshold": null,
"fraud_activity_block_threshold": null,
"fraud_profile_alert_threshold": null,
"fraud_profile_block_threshold": null,
"scrub_offer_pixels": null,
"shared": "0"
}
}
It is not necessary to create concrete classes for explicit deserialization. Obviously that is a perfectly valid approach, however, if that's your style preference.
See http://james.newtonking.com/projects/json/help/LINQtoJSON.html for more examples.
I think you can try creating a simple example, not a huge json like that one.
Take a look at http://servicestack.net/ it is an alternative to Json.NET, it is faster and the learning curve is small. You can find a lot of examples on the website.
Is this in javascript? You should be able to just do this:
JSON.parse(response.data)

Categories