JSON.Net Deserialization of non-generic Root Objects - c#

I'm currently working on a project where I make a request to the Riot Games API, parse the JSON, and do some stuff with it. I have the request working, and I know I'm getting valid JSON. My issue is using JSON.Net to deserialize the JSON.
The JSON is of the following structure:
{
"xarcies": {
"id": 31933985,
"name": "Farces",
"profileIconId": 588,
"revisionDate": 1450249383000,
"summonerLevel": 30
}
}
I want to load this data into the following class
[JsonObject(MemberSerialization.OptIn)]
class Summoner
{
[JsonProperty("id")]
public long id {get;set;}
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("profileIconId")]
public int profileIconId { get; set; }
[JsonProperty("revisionDate")]
public long revisionDate { get; set; }
[JsonProperty("summonerLevel")]
public long summonerLevel { get; set; }
}
The issue I'm having is that because I'm given a "xarcies" object that contains the information I need, I'm not sure how to go about designing a class that can accept the JSON data. I've seen some examples that use a RootObject class to take the object and that class has a subclass that all the pairs are put into, but I can't seem to get it to work. Every time I run it the attributes for the object end up being NULL.

You can deserialize your JSON as a Dictionary<string, Summoner>:
var root = JsonConvert.DeserializeObject<Dictionary<string, Summoner>>(jsonString);
The dictionary will be keyed by the user name, in this case "xarcies". See Deserialize a Dictionary.

I just used json2csharp to create the following class (its types look a bit different then yours):
public class UserData
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public long revisionDate { get; set; }
public int summonerLevel { get; set; }
}
public class RootObject
{
public KeyValuePair<string, UserData> value { get; set; }
}

Related

C# JObject Unexpected token when deserializing multidimensional array

I am using JObject to read various api responses. With the following json
{"API":{"Year":["2020","2019","2018","2017","2016","2015"],
"Status": {"Message":"The call returned successfully with years"}}}
I can use this:
dynamic json= JObject.Parse(s);
string[] yrs = json.API.Year.ToObject<string[]>();
where s is the json object.
This works perfectly to give me a simple array of years.
I am having difficulty parsing multi dimensions in the json response. when i have the following:
{"API":{"Category":[
{"GroupName":"Exterior Accessories","GroupID":"2",
"Items":
[{"Id":"64","Value":"Body Part"},
{"Id":"20","Value":"Body Styling"},
{"Id":"7","Value":"Bras and Hood Protectors"}]
},
{"GroupName":"Interior Accessories","GroupID":"4",
"Items":
[{"Id":"21","Value":"Carpet",
{"Id":"2","Value":"Doors and Components"},
{"Id":"8","Value":"Floor Protection"}]
},
],
"Status": {"Message":"The call (api.v12.estore.catalograck.com) returned successfully with categories.","DataFound":true,"TimeStamp":"02/02/2020 11:48:27","InternalError":false}}}
How can I parse this into a multi-dimensional array?
Since Years you used was a simple built in element (string), you dont need to create any classes.. but the Categories you have in your JSON is a object. To access the Categories in a way you can access its elements, I would recommend creating the necessary classes and then using the Category list of the root object to do what you need.
Example code
public class Item
{
public string Id { get; set; }
public string Value { get; set; }
}
public class Category
{
public string GroupName { get; set; }
public string GroupID { get; set; }
public List<Item> Items { get; set; }
}
public class Status
{
public string Message { get; set; }
public bool DataFound { get; set; }
public string TimeStamp { get; set; }
public bool InternalError { get; set; }
}
public class API
{
public List<Category> Category { get; set; }
public Status Status { get; set; }
}
public class RootObject
{
public API API { get; set; }
}
Above are the needed classes for succesful deserialization where RootObject class is the parent.
Use the following in your Main method.,
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
List<Category> categories = root.API.Category;

Consume Data From this endpoint

I am getting tdata from a certain endpoint and the problem id on serialization to my classes. I want to cast the bellow data to my class but cant get how the class should be structured. Check out the data .....
{
"-LYG_AI_oGYjNBrzMlKF": {
"chatDispayText": "",
"chatId": "-LYG_AI_oGYjNBrzMlKF",
"chatName": "",
"chattype": "single",
"imageUrl": "https://wallpaper.wiki/wp-content/uploads/2017/04/wallpaper.wiki-Amazing-celebrities-hd-wallpaper-PIC-WPD004734.jpg",
"lastMessageSent": "aiye",
"lastMessageSentTime": 1549704416263,
"synched": false,
"users": {
"-LYG_AIZ5MvTbjR7DACe": "Uicpm3L15TX0c15pKCI6KUEARyB3",
"-LYG_AI_oGYjNBrzMlKE": "Xsr0z9lsqNOEytX61lJvaGz1A8F2"
}
}
}
If the data you get out the endpoint has a dynamic structure, you can make use of a key-vale pair collection or a dictionary. For instance:
JObject jObject = JObject.Parse(Data); // This would already give you a key-value pair collection
Dictionary<String,Object> collection = new Dictionary<String, Object>();
foreach(var obj in jObject){
collection.Add(obj.Key, obj.Value);
}
However, this isn't a strongly typed approach which means that it is not effective in the majority of scenarios. A better solution when dealing with endpoints would be to define a class with fixed schema, actually something you need in your code, and then map the class to the object yielded by the endpoint using a metadata struct. For example:
public class ChatInfoModel
{
[JsonProperty(Metadata.ChatId)]
public long ChatId { get; set; }
[JsonProperty(Metadata.ChatId, Required = Required.AllowNull)]
public String Message { get; set; }
}
public struct Metadata
{
public const String ChatId = "userChatId";
public const String Message = "messageTxt";
}
And then
var deserializedObject = JsonConvert.DeserializeObject<ChatInfoModel>(data);
However, if your class has the exact same naming convention (but should not necessarily follow the camelCase naming convention) for its properties as in the serialized data, the JsonProperty attribute would not be needed.
You can also deserialize the object without using JsonProperty attribute manually using the first approach, and it is actually advantageous in certain scenarios where your schema comes from a configuration file rather than a struct.
Take inspiration from the Structure below:
public class Rootobject
{
public LYG_AI_Ogyjnbrzmlkf LYG_AI_oGYjNBrzMlKF { get; set; }
}
public class LYG_AI_Ogyjnbrzmlkf
{
public string chatDispayText { get; set; }
public string chatId { get; set; }
public string chatName { get; set; }
public string chattype { get; set; }
public string imageUrl { get; set; }
public string lastMessageSent { get; set; }
public long lastMessageSentTime { get; set; }
public bool synched { get; set; }
public Users users { get; set; }
}
public class Users
{
public string LYG_AIZ5MvTbjR7DACe { get; set; }
public string LYG_AI_oGYjNBrzMlKE { get; set; }
}

Deserialize JSON objects one by one using json.net (XAMARIN)

I'm new to this. I'm using Xamarin in VS2017.
I have a JSON file as follows
[ {
"LEDGERID":1,
"LEDGERNAME":"CASH",
"UNDER":"19",
"CREDIT_PERIOD":"0",
"CREDIT_LIMIT":"0",
"LEDGER_TYPE":"DEBIT",
"OPENBAL":120196.00,
"STATUS":"True",
"USER_GEN":false,
"date":null,
"arabic_name":null},
{
"LEDGERID":2,
"LEDGERNAME":"PURCHASE",
"UNDER":"17",
"CREDIT_PERIOD":"0",
"CREDIT_LIMIT":"0",
"LEDGER_TYPE":"DEBIT",
"OPENBAL":0.00,
"STATUS":"True",
"USER_GEN":false,
"date":null,
"arabic_name":null
}
]
This is a lengthier one but i made it short for easy understanding. I need to take it one by one because sometimes I need to give test cases before taking the values to the list. I am using PCL storage in XAMARIN tostore the Json File. I went througn the documents of NewtonSoft Json deserializing. I hope some one can help me thanks in advance
Your json isn't valid, you had the word nul, however i'm sure it was a mistake
Take your json to http://json2csharp.com/ and create a class from it and call it what ever you want
Get your self the Json.net Nuget package
Example class
public class RootObject
{
public int LEDGERID { get; set; }
public string LEDGERNAME { get; set; }
public string UNDER { get; set; }
public string CREDIT_PERIOD { get; set; }
public string CREDIT_LIMIT { get; set; }
public string LEDGER_TYPE { get; set; }
public double OPENBAL { get; set; }
public string STATUS { get; set; }
public bool USER_GEN { get; set; }
public object date { get; set; }
public object arabic_name { get; set; }
}
Usage
var results = JsonConvert.DeserializeObject<List<RootObject>>(json);

Dynamic/Expando and JSON

There's a lot of Qs on this, but I need a solution without JSON.Net, etc. - I must use the canned stuff in Asp.Net MVC.
How can I serialize a POCO with a dynamic property - and get all the static properties, too? What I found was the dynamic only, or the static type which is easy.
e.g.
public class ReturnThisClassAsJSON {
public int Id {get; set; }
public string Name { get; set; }
public ContainedClass ContainedContents { get; set; }
}
public class ContainedClass {
public int Order { get; set; }
public string Label { get; set; }
public dynamic DynamicInfo { get; set; }
public List<dynamic> DynamicList { get; set }
}
My own answer:
I replaced the dynamic from the DynamicInfo and DynamicList from the ContainedClass with static types.
With the dynamic, I had 1 of 2 choices. Either serialize the dynamic to a string in its own serialization call using above SO question 5156664. (Which left me with the rest of the class I also wanted serialized and merged with it, thus this question). Or, incur this error:
"A circular reference was detected while serializing an object of type 'System.Reflection .RuntimeModule' ".
when attempting a single serialization call on the ContainedClass.
So, I transferred the dynamics into static-typed classes:
public class ColumnValue
{
public string Name { get; set; }
public string Value { get; set; }
}
public class DynamicRow
{
public List<ColumnValue> ColumnValue { get; set; }
}
and, change ContainedClass to this:
public class ContainedClass
{
public List<ColumnValue> DynamicInfo { get; set; }
public List<DynamicRow> Data { get; set; }
}
And, it serializes using out-of-the-box Asp.Net MVC:
return Json(ReturnThisClassAsJSON, JsonRequestBehaviour.AllowGet);

Deserialize JSON with variable name arrays

I am getting JSON that is being returned from a REST web service for survey responses. It has arrays for the name portion of some of the name value pairs. Additionally the names will be variable depending on the type of questions asked. I'm using JSON.net and trying to deserialize the returned value into some type of object tree that I can walk but can't figure out what structure to use to have it filled in.
I tested the following snippet in LinqPad and fields is always empty. Is there someway to easily read in the variable data or do I have to parse it in code?
void Main() {
string json = #"{
'result_ok':true,
'total_count':'51',
'data':[{
'id':'1',
'status':'Deleted',
'datesubmitted':'2015-01-12 10:43:47',
'[question(3)]':'Red',
'[question(4)]':'Blue',
'[question(18)]':12,
'[variable(\'STANDARD_IP\')]':'127.0.0.1',
'[variable(\'STANDARD_GEOCOUNTRY\')]':'United States'
}]
}";
var responses = JsonConvert.DeserializeObject<RootObject>(json);
responses.Dump();
}
public class RootObject {
public bool result_ok { get; set; }
public string total_count { get; set; }
public List<Response> data { get; set; }
}
public class Response {
public string id { get; set; }
public string status { get; set; }
public string datesubmitted { get; set; }
public List<object> fields = new List<object>();
}
Change the fields property in your Response class to be a Dictionary<string, object>, then mark it with a [JsonExtensionData] attribute like this:
public class Response
{
public string id { get; set; }
public string status { get; set; }
public string datesubmitted { get; set; }
[JsonExtensionData]
public Dictionary<string, object> fields { get; set; }
}
All of the fields with the strange property names will then be placed into the dictionary where you can access them as normal. No extra code is required.
Here is a demo: https://dotnetfiddle.net/1rQUXT

Categories