Deserialize nested JSON into Dictionary, string and class - c#

I have a JSON that I'd like to DeserializeObject into an outerDictionary with innerDictionary and innermostClass as so:
var entityMap = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, fieldClass>>>(File.ReadAllText("map.json"));
However, the innerDictionary may have a string:string instead of string:innerMostClass.
{
"Client": {
"__class__": "contact",
"ClientId": {
"__field__": "new_ndisclientid",
"__type__": "string"
},
"GivenName": {
"__field__": "firstname",
"__type__": "string"
},
},
"Case": {
"__class__": "contact",
"CaseId": {
"__field__": "new_ndiscaseid",
"__type__": "string"
}
}
}
Is there a way to do this? I don't want to make all of it into Classes.
Is it possible to do this with a custom JsonConverter?
EDIT: Renamed classname to entityName for clarity. ClientId and GivenName would be deserialized into fieldClasses.

You can use dynamic or object instead of inner class
var json =
"{\r\n\t\"Client\": {\r\n\t\t\"__entityName__\": \"contact\",\r\n\r\n\t\t\"ClientId\": {\r\n\t\t\t\"__field__\": \"new_ndisclientid\",\r\n\t\t\t\"__type__\": \"string\"\r\n\t\t},\r\n\t\t\"GivenName\": {\r\n\t\t\t\"__field__\": \"firstname\",\r\n\t\t\t\"__type__\": \"string\"\r\n\t\t}\r\n\t}\r\n}";
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, dynamic>>>(json);
List<object> values = deserialized.SelectMany(result => result.Value).Cast<object>().ToList();
If you want separate inner class
public class Client
{
public string __entityName__ { get; set; }
public Dictionary<string, string> ClientId { get; set; }
public Dictionary<string, string> GivenName { get; set; }
}
var deserializedWithClass = JsonConvert.DeserializeObject<Dictionary<string, Client>>(json);

Deserialize nested JSON into Class. not on dictionary based but it's useful.
Step 01: open the link https://jsonformatter.org/json-parser
Step 02: copy the down contents.
{
"Client": {
"__class__": "contact",
"ClientId": {
"__field__": "new_ndisclientid",
"__type__": "string"
},
"GivenName": {
"__field__": "firstname",
"__type__": "string"
}
},
"Case": {
"__class__": "contact",
"CaseId": {
"__field__": "new_ndiscaseid",
"__type__": "string"
}
}
}
Step 03: Open above link. copy contents and past in to left side and click on to JSON Parser button. Look like below image.
Step 04: Click on download button. Downloading the jsonformatter.txt file. Successfully download the file as jsonformatter.txt.
Step 05: Copy step 02 content and open url https://json2csharp.com/.Copy contents and past in to left side and click on to Convert button. Look like below image.
Step 06: In Scripting.
(A) Create myRootClass.cs file and copy and past down contents to your file.[[System.Serializable] it's used in unity 3d software c# scripting]
[System.Serializable]
public class myRootClass
{
[System.Serializable]
public class ClientId
{
public string __field__ { get; set; }
public string __type__ { get; set; }
}
[System.Serializable]
public class GivenName
{
public string __field__ { get; set; }
public string __type__ { get; set; }
}
[System.Serializable]
public class Client
{
public string __class__ { get; set; }
public ClientId ClientId { get; set; }
public GivenName GivenName { get; set; }
}
[System.Serializable]
public class CaseId
{
public string __field__ { get; set; }
public string __type__ { get; set; }
}
[System.Serializable]
public class Case
{
public string __class__ { get; set; }
public CaseId CaseId { get; set; }
}
[System.Serializable]
public class Root
{
public Client Client { get; set; }
public Case Case { get; set; }
}
}
(B) Read the jsonformatter.txt file.
// Read entire text file content in one string
string textFilePath = "C:/Users/XXX/Downloads/jsonformatter.txt";//change path
string jsontext = System.IO.File.ReadAllText(textFilePath);
Debug.Log("Read Json"+jsontext);// used Console.Writeline
(C) Convert string into C# and show the data.
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(jsontext);
var client = myDeserializedClass.Client;
Debug.Log("client.__class__ :- "+client.__class__); //used Console.Writeline
Debug.Log("client.ClientId.__field__ :- "+client.ClientId.__field__);// used Console.Writeline
Debug.Log("client.GivenName.__field__ :- "+client.GivenName.__field__);// used Console.Writeline

Related

Parsing json. Field could be plain text and object

Shortly, I'm trying to create some web-API-application and I'm parsing telegram data and I am faced up with a problem.
When I get all the JSON, I see that the program can't parse it because some field(text) couldn't resolve the object(code snip below). I'm thinking about creating a custom JSON converter(that's annoying, so that's the reason why I'm here), but maybe I just don't know how to do it correctly.
Here are examples:
{
"text": "SOME VERY VERY VERY PRIVATE INFORMATION",
},
AND
{
"text": [
{
"type": "link",
"text": "SOME VERY VERY VERY PRIVATE LINK :D(probably, onlyfans)"
}
],
}
I usually use a JsonConstructor in this case. You don't need to pass all properties into the constructor, you can pass only the properties that cause a problem.
using Newtonsoft.Json;
Data data = JsonConvert.DeserializeObject<Data>(json);
public class Data
{
public List<Text> text { get; set; }
[JsonConstructor]
public Data(JToken text)
{
if (text.Type == JTokenType.String)
this.text = new List<Text> { new Text { text = (string)text } };
else this.text = text.ToObject<List<Text>>();
}
}
public class Text
{
public string type { get; set; }
public string text { get; set; }
}
I would use system.text.json More info here
and here
public class Data
{
[JsonPropertyName("text")]
public IEnumerable<TextInformation> TextInformations{ get; set; }
}
public class TextInformation
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
and use it like this
var text = JsonSerializer.Deserialize<Data>(jsonString)

Deserialize issue in C# Json

PageParameters have dynamic values. I tried to add it like below.
{
"Message": [
{
"TextMessage": "Hello World",
"Notification": [{
"Page": "Order",
"OpenPage": true,
"PageParameters":[ {"filedName": "400","filedvalue": "test","test": "444"}]
} ]
}
]
}
C# Code
var notification = notificationRequest?.NotificationMessage[0].ToString();
var NotificationObj = JsonConvert.DeserializeObject<NotificationObj>(notification);
public class NotificationObj
{
public string TextMessage { get; set; }
public string AppName { get; set; }
public List<Notifications> Notification { get; set; }
}
public class Notifications
{
public string PageName { get; set; }
public bool OpenPage { get; set; }
public List<PageParameter> PageParameters { get; set; }
}
public class PageParameter
{
List<string> PageParameters = new List<string>();
}
My PageParameter have dynamic values. Its getting multiple values. So i tried to add it as a List. But its not adding values when Deserialize Json. Other values are adding. Please help to solve this.
Check my answer here. You essentially need to apply that on your PageParameter class
PageParameters is an array of Key-value pairs, which would require the use of a Dictionary in C#.
Update PageParameter to the following and re-run your deserialization:
public class PageParameter
{
Dictionary<string, string> PageParameters = new Dictionary<string, string>();
}

Return JSON from API method

I am using ASP.net Core web api (c#) here
I have a JSON string as:
{
"userId":321,
"account":"new
"fname":"Adam",
"lname":"Silver"
"features":[
{
"available":true,
"status":open,
"admin":false
}
]
}
I want to test this data in my angular code so wanted to hardcode this into my API; then I want my API to return this back. What I am finding it hard is how to return this. Shall I return this as a string or need to parse it?
I have this method in my API:
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
Do I need to represent this into string or parse it someway?
Your JSON is invalid. We need to correct it. JSONLint can be helpful for that. I took your JSON and corrected the syntax errors until I got this:
{
"userId": 321,
"account": "new",
"fname": "Adam",
"lname": "Silver",
"features":[
{
"available": true,
"status": "open",
"admin": false
}
]
}
Then I need to generate a C# class structure to represent this JSON. I could manually create it, but the excellent json2csharp.com can generate it for me quickly. I fed this JSON into and received the following classes back:
public class Feature
{
public bool available { get; set; }
public string status { get; set; }
public bool admin { get; set; }
}
public class RootObject
{
public int userId { get; set; }
public string account { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public List<Feature> features { get; set; }
}
I put these class definitions into my application. Then I need to modify my action method to create an instance of this RootObject class (you should change the name to actually match what it's intended for).
[HttpGet]
public ActionResult<RootObject> Get()
{
// Create an instance of our RootObject and set the properties
var myRootObject = new RootObject();
myRootObject.userId = 321;
myRootObject.account = "new";
myRootObject.fname = "Adam";
myRootObject.lname = "Silver";
myRootObject.features = new List<Feature>();
// Create an instance of a feature and set its properties
var feature = new Feature();
feature.available = true;
feature.status = "open";
feature.admin = false;
// Add the new feature to the features collection of our RootObject
myRootObject.features.Add(feature);
// Return the instance of our RootObject
// The framework will handle serializing it to JSON for us
return myRootObject;
}
Note that I changed the signature of your method. I made it no longer accept an IEnumerable because it wasn't clear why you had that. And I changed it to return an ActionResult after checking Microsoft's documentation.
Hi Please find correct JSON format for above one:
{
"userId": 321,
"account": "new",
"fname": "Adam",
"lname": "Silver",
"features": [{
"available": true,
"status": "open",
"admin": false
}]
}
you can use below class in your web API to pass respective data
public class Feature
{
public bool available { get; set; }
public string status { get; set; }
public bool admin { get; set; }
}
public class RootObject
{
public int userId { get; set; }
public string account { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public List<Feature> features { get; set; }
}
then at the end, while returning data, convert the respective class object into JSON by serializing that into JSON format.
Hope it will fulfill your requirement.
Putting the comments into an answer:
If you are using ActionResult, I'll assume you are using asp.net mvc. What you want is JsonResult.
[HttpGet]
public JsonResult Get()
{
return new JsonResult
{
Data = new
{
userId = 321,
account = new
{
fname = "Adam",
lname = "Silver",
features = new object[]{
new
{
available = true,
status = "open",
admin = false
}
}
}
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

Deserialize List<Object> using NewtonSoft. Cannot convert IList

I am trying to parse a List of Comment objects from here. A comment object is a class in the leankit namespace: LeanKit.API.Client.Library.TransferObjects.Comment but I get an error in the final line of the block below specifically over responseString:
cannot convert from 'System.Collections.Generic.IList' to string
Why am I getting this? I am specifying a custom class I created specifically to deserialize the list:
public class MyCommentList
{
public string ReplyText { get; set; }
public List<Comment> ReplyData { get; set; }
public string ReplyCode { get; set; }
}
calling the class
var url = "https://" + acctName + ".leankit.com/kanban/api/card/getcomments/" + boardid + "/" + cardid;
var responseString = await url.WithBasicAuth("xxx", "yyy").GetJsonListAsync();
MyCommentList mycomment = JsonConvert.DeserializeObject<MyCommentList>(responseString);
a cleaner version of calling the class (using Flurl):
var url = "https://" + acctName + ".leankit.com/kanban/api/card/getcomments/" + boardid + "/" + cardid;
MyCommentList mycomment = await url.WithBasicAuth("xxx", "yyy").GetAsync().ReceiveJson<MyCommentList>();
The JSON structure (from the link above) reproduced here:
{
"ReplyData": [
[
{
"Id": 256487698,
"Text": "First comment for this card.",
"TaggedUsers": null,
"PostDate": "10/14/2015 at 04:36:02 PM",
"PostedByGravatarLink": "3ab1249be442027903e1180025340b3f",
"PostedById": 62984826,
"PostedByFullName": "David Neal",
"Editable": true
}
]
],
"ReplyCode": 200,
"ReplyText": "Card comments successfully retrieved."
}
In the JSON, "ReplyData" is a 2d jagged array:
{
"ReplyData": [ [ ... ] ],
}
In you model it is a 1d list:
public List<Comment> ReplyData { get; set; }.
You need to change it to public List<List<Comment>> ReplyData { get; set; } to reflect the actual JSON:
public class MyCommentList
{
public string ReplyText { get; set; }
public List<List<Comment>> ReplyData { get; set; }
public string ReplyCode { get; set; }
}
Where I assume Comment is taken from https://github.com/LeanKit/LeanKit.API.Client/blob/master/LeanKit.API.Client.Library/TransferObjects/Comment.cs.
If there is a chance that it is sometimes a 1d array and sometimes a 2d array, you may need to apply SingleOrArrayConverter<Comment> from this answer to How to handle both a single item and an array for the same property using JSON.net by Brian Rogers like so:
public class MyCommentList
{
public string ReplyText { get; set; }
[JsonProperty(ItemConverterType = typeof(SingleOrArrayConverter<Comment>))]
public List<List<Comment>> ReplyData { get; set; }
public string ReplyCode { get; set; }
}
Working sample .Net fiddle here.

Deserializing just a single node of a JSON response

I have a json response like
{
"appStatus":{
"status":true
},
"lastSyncDate":"06-07-2013 13.54.27",
"configResponse":{
"status":{
"status":true
},
"configs":{
"APPLOGENABLED":{
"configCode":"APPLOGENABLED",
"configDesc":"enable or disable logging from front end",
"configType":"TAB",
"configValue":"Y"
},
"COMMENTSTIMER":{
"configCode":"COMMENTSTIMER",
"configDesc":"timer for comments in seconds",
"configType":"TAB",
"configValue":"60"
},
"SUMMARYTIMER":{
"configCode":"SUMMARYTIMER",
"configDesc":"timer for summary in seconds",
"configType":"TAB",
"configValue":"30"
},
"ALERTSTIMER":{
"configCode":"ALERTSTIMER",
"configDesc":"timer for alerts in seconds",
"configType":"TAB",
"configValue":"60"
}
},
"lastSyncDate":"06/07/2013 13.48.13"
}
}
Using json.NET, I want to extract configResponse into dictionary. I know i can directly convert a Dictionary object like this
JsonConvert.DeserializeObject<Dictionary<string,string>>()....
but since configResponse is a sub element, I am not able to parse it as required.
I want to deserialize the above json response as
public class ConfigResponse
{
public Status status { get; set; }
public Dictionary<string, ConfigurationItem> configs { get; set; }
public string lastSyncDate { get; set; }
}
public class ConfigurationItem
{
public String configCode { get; set; }
public String configDesc { get; set; }
public String configType { get; set; }
public String configValue { get; set; }
}
You can parse JSON string into JObject, get sub-object "configResponse", then deserialize it into ConfigResponse. It's one line of code:
JObject.Parse("{...}")["configResponse"].ToObject<ConfigResponse>()
If you need a custom serializer to set deserialization options, you can pass it to ToObject<T>() method.
i have only use this method and it worked.
await JsonConvert.DeserializeObjectAsync<ConfigResponse>(jsontoobject, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

Categories