Query or deserialize json with dynamic keys using System.Text.Json - c#

I have json that looks like this, the key "123" could be any number.
{
"key1": "",
"key2": {
"items": {
"123": {
"pageid": 123,
"name": "data"
}
}
}
}
I want to deserialize or query the json with System.Text.Json so i can get the value of the key "name". How can I do that with System.Text.Json? I'm using .NET Core 3.1.

Since one of the json keys can vary ("123"), this can be represented by a Dictionary<>. The following classes model your json.
public class ItemProps
{
public int pageid { get; set; }
public string name { get; set; }
}
public class Item
{
public Dictionary<string, ItemProps> items { get; set; }
}
public class Root
{
public string key1 { get; set; }
public Item key2 { get; set; }
}
Then to deserialize using System.Text.Json you would use:
var data = JsonSerializer.Deserialize<Root>(json);
To access name:
var name = data.key2.items["123"].name
Try it online
Note, I named the classes quickly... please consider giving the classes better names, more descriptive names.

Something like:
public class Rootobject
{
public string key1 { get; set; }
public InnerObject key2 { get; set; }
}
public class InnerObject
{
public Dictionary<string, ObjectTheThird> items { get; set; }
= new Dictionary<string, ObjectTheThird>();
}
public class ObjectTheThird
{
public int pageid { get; set; }
public string name { get; set; }
}
and use the APIs on Dictionary<,> to look at the items. Or you just want the first:
var name = obj.key2.items.First().Value.name;

Related

How to display JSON data (nested) in C#

I am fetching an API that returns a JSON response like this:
{
"id": 161635,
"rev": 1,
"fields": {
"System.Url": "http://google.com",
"System.Type": "Bug",
"System.State": "New",
"System.AssignedTo": {
"displayName": "John Doe"
}
}
}
I want to display the id and everything inside fields.
This is my model:
public class WorkItemDetail {
public int id { get; set; }
public Dictionary<string, object> fields {get;set;}
}
Here is the problem, I can display the id and everything in fields except for some reason, I can't show displayName
Here is what I doing:
#WorkItemDetailResponse.id
#WorkItemDetailResponse.fields["System.WorkItemType"];
#WorkItemDetailResponse.fields["System.State"];
#WorkItemDetailResponse.fields["System.AssignedTo"];
#WorkItemDetailResponse.fields["System.AssignedTo"]["displayName"]; <!-- does not work -->
#code{
WorkItemDetailResponse = JsonConvert.DeserializeObject<WorkItemDetail>(ResponseBody);
}
I am new to C# so I don't know why this line is not working
#WorkItemDetailResponse.fields["System.AssignedTo"]["displayName"]
Create your DTO structure as follows:
public class Fields
{
[JsonProperty("System.Url")]
public string SystemUrl { get; set; }
[JsonProperty("System.Type")]
public string SystemType { get; set; }
[JsonProperty("System.State")]
public string SystemState { get; set; }
[JsonProperty("System.AssignedTo")]
public SystemAssignedTo SystemAssignedTo { get; set; }
}
public class WorkItemDetail
{
public int id { get; set; }
public int rev { get; set; }
public Fields fields { get; set; }
}
public class SystemAssignedTo
{
public string displayName { get; set; }
}
here's fiddle: https://dotnetfiddle.net/F9Wppv
another way - using dynamic variable: https://dotnetfiddle.net/Goh7YY
You need to cast the object value to a JObject
((JObject)JsonConvert.DeserializeObject<WorkItemDetail>(json).fields["System.AssignedTo"])["displayName"]
JSON.Net will create a JObject if the property type is object and the value is a JSON object.
db<>fiddle

How to parse JSON dynamic KeyValuePair to C# model in Blazor WASM [duplicate]

I have json that looks like this, the key "123" could be any number.
{
"key1": "",
"key2": {
"items": {
"123": {
"pageid": 123,
"name": "data"
}
}
}
}
I want to deserialize or query the json with System.Text.Json so i can get the value of the key "name". How can I do that with System.Text.Json? I'm using .NET Core 3.1.
Since one of the json keys can vary ("123"), this can be represented by a Dictionary<>. The following classes model your json.
public class ItemProps
{
public int pageid { get; set; }
public string name { get; set; }
}
public class Item
{
public Dictionary<string, ItemProps> items { get; set; }
}
public class Root
{
public string key1 { get; set; }
public Item key2 { get; set; }
}
Then to deserialize using System.Text.Json you would use:
var data = JsonSerializer.Deserialize<Root>(json);
To access name:
var name = data.key2.items["123"].name
Try it online
Note, I named the classes quickly... please consider giving the classes better names, more descriptive names.
Something like:
public class Rootobject
{
public string key1 { get; set; }
public InnerObject key2 { get; set; }
}
public class InnerObject
{
public Dictionary<string, ObjectTheThird> items { get; set; }
= new Dictionary<string, ObjectTheThird>();
}
public class ObjectTheThird
{
public int pageid { get; set; }
public string name { get; set; }
}
and use the APIs on Dictionary<,> to look at the items. Or you just want the first:
var name = obj.key2.items.First().Value.name;

Deserialize JSON using specific properties

I'm trying to deserialize JSON without declaring every property in C#. Here is a cut-down extract of the JSON:
{
"resourceType": "export",
"type": "search",
"total": 50,
"timestamp": "2020-08-02T18:26:06.747+00:00",
"entry": [
{
"url": "test.com/123",
"resource": {
"resourceType": "Slot",
"id": [
"123"
],
"schedule": {
"reference": {
"value": "testvalue"
}
},
"status": "free",
"start": "2020-08-03T08:30+01:00",
"end": "2020-08-03T09:00+01:00"
}
}
]
}
I want to get the values out of entry → resource, id and start.
Any suggestions on the best way to do this?
I've made very good experiences with json2sharp. You can enter your JSON data there and it will generate the classes you need to deserialize the JSON data for you.
public class Reference
{
public string value { get; set; }
}
public class Schedule
{
public Reference reference { get; set; }
}
public class Resource
{
public string resourceType { get; set; }
public List<string> id { get; set; }
public Schedule schedule { get; set; }
public string status { get; set; }
public string start { get; set; }
public string end { get; set; }
}
public class Entry
{
public string url { get; set; }
public Resource resource { get; set; }
}
public class Root
{
public string resourceType { get; set; }
public string type { get; set; }
public int total { get; set; }
public DateTime timestamp { get; set; }
public List<Entry> entry { get; set; }
}
The next step is to choose a framework which will help you to deserialize. Something like Newtonsoft JSON.
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
If you want to get the data without declaring classes, you can use Json.Net's LINQ-to-JSON API (JToken, JObject, etc.). You can use the SelectToken method with a JsonPath expression to get what you are looking for in a couple of lines. Note that .. is the recursive descent operator.
JObject obj = JObject.Parse(json);
List<string> ids = obj.SelectToken("..resource.id").ToObject<List<string>>();
DateTimeOffset start = obj.SelectToken("..resource.start").ToObject<DateTimeOffset>();
Working demo here: https://dotnetfiddle.net/jhBzl4
If it turns out there are actually multiple entries and you want to get the id and start values for all of them, you can use a query like this:
JObject obj = JObject.Parse(json);
var items = obj["entry"]
.Children<JObject>()
.Select(o => new
{
ids = o.SelectToken("resource.id").ToObject<List<string>>(),
start = o.SelectToken("resource.start").ToObject<DateTimeOffset>()
})
.ToList();
Demo: https://dotnetfiddle.net/Qe8NB7
I am not sure why you don't deserialize the lot (even if it's minimally populated) since you have to do the inner classes anyway.
Here is how you could bypass some of the classes (1) by digging into the JObjects
Given
public class Reference
{
public string value { get; set; }
}
public class Schedule
{
public Reference reference { get; set; }
}
public class Resource
{
public string resourceType { get; set; }
public List<string> id { get; set; }
public Schedule schedule { get; set; }
public string status { get; set; }
public string start { get; set; }
public string end { get; set; }
}
public class Entry
{
public string url { get; set; }
public Resource resource { get; set; }
}
You could call
var results = JObject.Parse(input)["entry"]
.Select(x => x.ToObject<Entry>());

How to deserialize a Json string that has an array of objects but is not using square brackets

I'm trying to deserialize a Json string that has an array with no containing brackets.
{ "id": "983f90j30909j3f",
"moreInfo": {
"info193802": { ... },
"info920938": { ... },
"info849028": { ... }
}
}
This "moreInfo" is an array of items with dynamic keys and does not have square brackets telling that it's an array.
I've tried to deserialize it with Newtonsoft.Json normally ( JsonConvert.DeserializeObject<rootObject>() ) but since this json array isn't really an array it throws an error. Here is my class:
public class RootObject
{
public string Id { get; set; }
public MoreInfo MoreInfo { get; set; }
}
public class MoreInfo
{
public List<Info> InfoList{ get; set; }
}
public class Info
{
properties...
}
How do I go about deserializing this?
Update the root object to use IDictionary<string, Info>
public class RootObject {
public string Id { get; set; }
public IDictionary<string, Info> MoreInfo { get; set; }
}
the dynamic keys will be the key in the dictionary.
Once parsed you access the info via the dictionary's keys
Info info = rootObject.MoreInfo["info193802"];
Newtonsoft can correctly parse the data. The data represents objects, they happen to be nested fairly deep. You can accomplish it a couple of ways, for instance:
dynamic json = JsonConvert.DeserializeObject(response);
var info = json["moreinfo:info913802:example"].Value;
Your other option would be to use Visual Studio, let it create an object you can deserialize to.
Edit
Paste Special
As JSON
Output would be:
public class Rootobject
{
public string id { get; set; }
public Moreinfo moreInfo { get; set; }
}
public class Moreinfo
{
public Info193802 info193802 { get; set; }
public Info920938 info920938 { get; set; }
public Info849028 info849028 { get; set; }
}
public class Info193802
{
public string Example { get; set; }
}
public class Info920938
{
public string Example { get; set; }
}
public class Info849028
{
public string Example { get; set; }
}
The source JSON I used was yours, with one exception:
{ "id": "983f90j30909j3f",
"moreInfo": {
"info193802": { "Example" : "Blah" },
"info920938": { "Example" : "Blah" },
"info849028": {"Example" : "Blah" }
}
}

How can I map JSON to a .NET class

I want to map this JSON into a .NET class. How can I map this JSON data into a class? Please suggest how. Here is the json:
{"results": [
"43853",
"43855",
"43856",
"43857",
{
"questionType": 3,
"choiceAnswers": [123]
}
]}
The easiest solution is to use Visual Studio Edit > Paste Special > Paste Json As Classes.
But as your json is an array of different objects the .NET class will just be
public class JsonDto
{
public List<object> Results { get; set; }
}
A list of objects will be painful to work with so I recommend that you to use a typed model but then you need to specify you need to define the values, here's an example
{"results": [
{
"key1":"43853",
"key2":"43855",
"key3":"43856",
"key4":"43857",
"question": {
"questionType": 3,
"choiceAnswers": [123]
}
}
]};
public class JsonDto
{
public List<ResultDto> Results { get; set; }
}
public class ResultDto
{
public string Key1 { get; set; }
public string Key2 { get; set; }
public string Key3 { get; set; }
public string Key4 { get; set; }
public QuestionDto Question { get; set; }
}
public class QuestionDto
{
public int QuestionType { get; set; }
public List<int> ChoiceAnswers { get; set; }
}
You can use online converter to convert json data to c# models http://json2csharp.com For your json it would be something like this.
public class RootObject
{
public List<object> results { get; set; }
}

Categories

Resources