1

I am trying to use an RESTFUL API for an application we use internally. One call to the API returns the following JSON:

{
    "operation": {
        "name": "GET RESOURCES",
        "result": {
            "status": "Success",
            "message": "Query was successful"
        },
        "totalRows": 2,
        "Details": [{
            "RESOURCE DESCRIPTION": "Windows",
            "RESOURCE TYPE": "Windows",
            "RESOURCE ID": "101",
            "RESOURCE NAME": "WINDOWSPC",
            "NOOFACCOUNTS": "1"
        }, {
            "RESOURCE DESCRIPTION": "Ubuntu",
            "RESOURCE TYPE": "Linux",
            "RESOURCE ID": "808",
            "RESOURCE NAME": "UBUNTUPC",
            "NOOFACCOUNTS": "2"
        }]
    }
}

Using json.net I deseralize the json and check the stats with the following lines:

dynamic json = JsonConvert.DeserializeObject(response);
var status = json.operation.result.status.Value;

Next I want to get each value of each of the "Details" returned, but I cannot figure out how. I first tried getting the Details only with this:

var resourceList = json.operation.Details

Which works, but I cannot iterate over this to get just the "RESOURCE ID" and "RESOURCE NAME" for example.

I cannot use .Children() either, but when I hover over the resourceList there is a ChildrenTokens which seems to be what I want, but I cannot get at that in my code.

I also tried using resourceList as a DataSet as per their example but it throws an exception.

Can someone see what I am doing wrong..... I am not familiar with parsing JSON in C#

neildeadman
  • 3,974
  • 13
  • 42
  • 55
  • 1
    Copy your JSON string then use Paste Special ( Edit -> Paste Special -> Paste JSON as Classes), it will generate all necessary classes for you. – SᴇM Feb 10 '20 at 12:54
  • @SᴇM that sounds like something I could use.... but in my VS2019 Community, I don't have that option... – neildeadman Feb 10 '20 at 12:56
  • 1
    @neildeadman you do, it's available in all editions. In a C# file, go to the `Edit` menu and open the `Paste Special` submenu. The option doesn't appear in other text files – Panagiotis Kanavos Feb 10 '20 at 12:58
  • once you have the class define you can simply use the `DeserializeObject` with T your class. https://www.newtonsoft.com/json/help/html/DeserializeObject.htm – Drag and Drop Feb 10 '20 at 13:00
  • Does this answer your question? [Deserialize JSON into Object C#](https://stackoverflow.com/questions/34302845/deserialize-json-into-object-c-sharp) – Drag and Drop Feb 10 '20 at 13:00
  • @PanagiotisKanavos Its definitely not there, but on another machine I did have it so used that to generate and copied it over. Signed in on the one that worked and not on the one that didn't if that has any impact! – neildeadman Feb 10 '20 at 13:07
  • @neildeadman I know it's there because I use VS 2019 Community – Panagiotis Kanavos Feb 10 '20 at 13:09
  • Not sure if this your issue, but I was trying to map a JSON to a custom class and it failed due to whitespace in the variable names. The solution in my case was to use `[JsonProperty(PropertyName = "foo bar")]` to map the JSON content to a property manually. – display-name Feb 10 '20 at 13:10
  • @PanagiotisKanavos OK, well as I said, it was there on one install and not the other. I cannot prove that to you, so we'll just have to leave this there. – neildeadman Feb 10 '20 at 13:14
  • http://json2csharp.com/ and https://app.quicktype.io/#l=cs&r=json2csharp are online tool that does the same. If you do not have the option perhaps the Vs insallation is not complete. Quit devenv and start the visual studio installer, then [modify](https://i.stack.imgur.com/i5EzD.png) your current version and add https://i.stack.imgur.com/Q7lnV.png. it should give you the option. – Drag and Drop Feb 10 '20 at 13:16
  • @DragandDrop Ah, that'll be it. Dom't have the ASP.NET stuff installed :) – neildeadman Feb 10 '20 at 15:42

3 Answers3

2

You can use Json.Linq for that and parse a response into JObject, then iterate it foreach loop. It's possible, since Details is an array and JObject implements IDictionary<string, JToken> and IEnumerable<KeyValuePair<string, JToken>>

var jObject = JObject.Parse(response);

foreach (var detail in jObject["operation"]["Details"])
{
    var description = detail["RESOURCE DESCRIPTION"].Value<string>();
    //other properties
}
Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
1

Here's an example using the JObject class instead of dynamic

JObject json = JObject.Parse(response);

string status = json["operation"]["result"]["status"].Value<string>();

foreach (JToken resource in json["operation"]["Details"])
{
    string id = resource["RESOURCE ID"].Value<string>();
    string name = resource["RESOURCE NAME"].Value<string>();
}
Innat3
  • 3,561
  • 2
  • 11
  • 29
1

It is as simple as this:

Your Model classes would look like:

public class Result
{
    public string status { get; set; }
    public string message { get; set; }
}

public class Detail
{
    [JsonProperty("RESOURCE DESCRIPTION")]
    public string ResourceDescription { get; set; }
    [JsonProperty("RESOURCE TYPE")]
    public string ResourceType { get; set; }
    [JsonProperty("RESOURCE ID")]
    public string ResourceId { get; set; }
    [JsonProperty("RESOURCE NAME")]
    public string ResourceName { get; set; }
    [JsonProperty("NOOFACCOUNTS")]
    public string NoOfAccounts { get; set; }
}

public class Operation
{
    public string name { get; set; }
    public Result result { get; set; }
    public int totalRows { get; set; }
    public List<Detail> Details { get; set; }
}

public class RootObject
{
    public Operation operation { get; set; }
}

To de-serialize:

var json = JsonConvert.DeserializeObject<RootObject>(response);

To access a property:

var name=json.operation.name

To access your Details:

foreach(var item in json.operation.Details)
{
var myresourcename=item.ResourceName;
//So on
}
Rahul Sharma
  • 7,768
  • 2
  • 28
  • 54
  • Thanks, the other answers are shorter, but I am going to look into this more. – neildeadman Feb 10 '20 at 13:15
  • @neildeadman If you want a concrete implementation of your `JSON` into associated `Model` structure, then go ahead with this. – Rahul Sharma Feb 10 '20 at 13:19
  • I would use this approach as well, since you don't have to mess around with strings (less errors, IntelliSense support, etc.). – display-name Feb 10 '20 at 13:28
  • So another API call returns a different JSON that also has Operation, but is missing the TotalRows field. Am I best to implement a different class for each or can I implement multiple classes that are similar etc. – neildeadman Feb 10 '20 at 15:48
  • Yes, you can use this class for the other API response. Basically, you can define a Model structure for your base API response and use inheritance concept for your inner responses. – Rahul Sharma Feb 10 '20 at 15:51
  • @RahulSharma Can you point me to an example of such that I can read through and apply to my code? – neildeadman Feb 10 '20 at 16:05
  • Have you tried using the above class for your other API? There are many examples that you can find on the net with a model implementation of JSON with inheritance. – Rahul Sharma Feb 10 '20 at 16:26
  • @RahulSharma I did some quick Google searches but not sure I found precisely what you were referencing with the Model structure of classes and inheritance. FOr now I am implementing it the way others have suggested using `JObject` but I will look back at Model structures later to attempt to improve both the project and my knowledge. – neildeadman Feb 11 '20 at 09:16
  • @neildeadman You can refer to these questions and hopefully you can draw a general outline on your requirement using this method: https://stackoverflow.com/questions/40014615/how-to-create-models-in-asp-net-for-multi-level-json-format and https://stackoverflow.com/questions/19307752/deserializing-polymorphic-json-classes-without-type-information-using-json-net – Rahul Sharma Feb 11 '20 at 09:39