Search code examples
c#jsonrestsharp

How can I consume this nested JSON into a useable array using C#?


I am new to C# and have been struggling with this one problem for a few days. The API looks like this:

{
    "data": [
        {
            "id": "1730938253104377856",
            "user_id": "6c61d88c-7ff3-4cf1-b5cf-b05cc954d96b",
            "type": "security",
            "action": "user_switching_success",
            "entity_id": null,
            "ip_address": "xxxxx",
            "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
            "occurred_at": "2023-12-02T13:13:33Z",
            "created_at": "2023-12-02T13:13:33Z",
            "data": {
                "metadata": null,
                "target_uid": "c0eb0826-891f-4ea9-9d52-f2aba0cbc390",
                "occurred_at": "2023-12-02T13:13:33.399598788Z",
                "authentication_id": "",
                "has_authenticated": true
            },
            "old_data": null
        },
        {
            "id": "1730938253158903808",
            "user_id": "c0eb0826-891f-4ea9-9d52-f2aba0cbc390",
            "type": "security",
            "action": "signin",
            "entity_id": null,
            "ip_address": "xxxxxx",
            "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
            "occurred_at": "2023-12-02T13:13:33Z",
            "created_at": "2023-12-02T13:13:33Z",
            "data": {
                "metadata": null,
                "occurred_at": "2023-12-02T13:13:33.402810919Z",
                "captcha_verified": true,
                "authentication_id": ""
            },
            "old_data": null
        }
    ]
}

I have tried several variations of this code using Restsharp or Newtonsoft.json. I can get the "data" node back as one continuous string, but nothing I have tried has worked to get an array of the attributes populated so that I can use them in my program. I have seen dozens of examples of non-nested JSON, but I can't get the nested part to work. I really only need user_id, created_at, and action.

using RestSharp;
using System.Text.Json;
using System.Text.Json.Nodes;


class Program
{
    static void Main()
{

string apiUrl = "https://xxxx/auditlog_events";

// Make the REST API request
var restClient = new RestClient(apiUrl);
var request = new RestRequest("");
        request.AddHeader("accept", "application/json");
        request.AddHeader("authorization", "Bearer xxxx");
var response = restClient.Execute(request);

// Check if the request was successful
if (response.IsSuccessful)
{

            // Parse the JSON response into an array
            var jsonArray = JsonSerializer.Deserialize<JsonNode>(response.Content!)!;
            //var jsonArray = JsonSerializer.Deserialize<dataList>(response.Content!)!;
            // Process the array
            //Console.WriteLine(jsonArray);
            Console.WriteLine("{0}", jsonArray["data"]);
            //Console.WriteLine(jsonArray["type"]);
            //Console.WriteLine(jsonArray["action"]);

         
}
else
{
Console.WriteLine($"Error: {response.ErrorMessage}");
}
}
}

public class dataList
{
    public List<dataContainer> data;
}

public class dataContainer
{
    public data data;
}

public class data {
    public int id { get; set; }
    public string user_id { get; set; }
    public string type { get; set; }
    public string action { get; set; }
    public string entity_id { get; set; }
    public string ip_address { get; set; }
    public string user_agent { get; set; }
    public string occured_at { get; set; }
    public string created_at { get; set; }
    public string data { get; set; }
    public string old_data { get; set; }
    }

I was expecting to get attribute values in an array that I could use. I got one continuous string or null lists.


Solution

  • Your property mapping isn't correct. I fixed few issues for you and this works:

    public class dataContainer
    {
        public List<dataOuter> data { get; set; }
    }
    
    public class dataOuter
    {
        public string id { get; set; }
        public string user_id { get; set; }
        public string type { get; set; }
        public string action { get; set; }
        public string entity_id { get; set; }
        public string ip_address { get; set; }
        public string user_agent { get; set; }
        public string occured_at { get; set; }
        public string created_at { get; set; }
        public dataInner data { get; set; }
        public string old_data { get; set; }
    }
    
    public class dataInner
    {
        public string metadata { get; set; }
        public string target_uid { get; set; }
        public string occurred_at { get; set; }
        public string authentication_id { get; set; }
        public bool has_authenticated { get; set; }
    }
    

    Use this to deserialize:

    dataContainer jsonArray = JsonSerializer.Deserialize<dataContainer>(response.Content!)!;
    

    Also there is an issue converting the value in id to integer, I changed to string for now to get deserialize to work, but you can deal with the issue separately.

    One more thing, as you are new to C#, the standard for public properties is for them to start with Capital case, so they would be Id, User_Id, Action, etc.