Alan
Alan

Reputation: 2086

Retrieving JSON from API into C#

I am brand new to C# after working with PHP and Javascript for years and struggling with the arrays / lists.

I realize C# is a strongly typed language, but am still learning what that means. I am surprised there is no equivalent to PHP's print_r(), or var_dump() which I have always used extensively in development to verify things got the right values at the right time.

I am hitting some endpoints that return JSON from a URL shortener that looks like this:

[
    {
        "key": "WcoUC",
        "url": "https://www.shorty.com/WcoUC",
        "clicks": 17,
        "expires": "2017-12-22 15:30:00",
        "created_at": "2017-12-18 22:44:54",
        "updated_at": "2017-12-18 22:44:54",
        "redirect_to": "http://www.example2.com/"
    }
]

In my c# I have this method:

private static string start_get()
        {
            HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(string.Format("https://www.shorty.com/api/v1/urls"));

            WebReq.ContentType = "application/json; charset=utf-8";
            WebReq.Headers["Authorization"] = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOi7w8VePMIh5i3pZ-S329KifQ9TbWHfsqMfV-HXmhej_9KcQRReIbytrILzyopoXY7p7kKN6ZnZTrFO9P9-1y3ohFJCBxZXvW_iwbA9hsVTj9ZtFbJGxaaIlUZa19knuDirQ";
            WebReq.PreAuthenticate = true;


            HttpWebResponse WebResp = (HttpWebResponse)WebReq.GetResponse();

            Console.WriteLine(WebResp.StatusCode);
            Console.WriteLine(WebResp.Server);

            string jsonString;
            using (Stream stream = WebResp.GetResponseStream())
            {
                StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8);
                jsonString = reader.ReadToEnd();
            }

            List<Item> items = JsonConvert.DeserializeObject<List<Item>>(jsonString);
            return jsonString;
        }

With it's associated class:

public class Item
{
    public string key { get; set; }
    public string url { get; set; }
    public int clicks { get; set; }
    public string expires { get; set; }
    public string created_at { get; set; }
    public string updated_at { get; set; }
    public string redirect_to { get; set; }
}

This is all working, but I am a little confused about why I have to setup a class to access each item in the JSON. My concern is that if the API gets updated with new items, they won't show up. So for example, let's say there was a new key:value added of "referring_url":"http://www.stackoverflow.com". When I dump the value of item I won't see that there. I am so used to javascript where it would just be item.referring_url and could have as many nested objects as it wanted to have without needing to define every little part.

Is it possible during this declaration

List<Item> items = JsonConvert.DeserializeObject<List<Item>>(jsonString);

to automatically assign everything it knows how to from the class I defined, but then assign the leftover to something that gets logged to the console or something so I know to handle it?

Is there a better method that will autocreate the classes in a more familiar way to someone transitioning from javascript?

Upvotes: 1

Views: 135

Answers (5)

Alan
Alan

Reputation: 2086

The application I am building is a Windows Form, so Console.Write that is part of so many tutorials / examples was not much help, but I configured a multiline textbox named DebugBoxTest and in the Form1.cs placed:

public void DebugBoxUpdate(string incomingString)
{
    JArray array = JArray.Parse(incomingString);
    DebugBoxTest.Text = JsonConvert.SerializeObject(array, Formatting.Indented);
}

Now I can dump formatted things into it using something like this from the Main area:

string results = start_get();
ThisForm.DebugBoxUpdate(results);

I know there are a lot of ways to skin a cat, and I am too new to properly upvote answers, but will accept whichever is at the top based off others feedback.

In the future I may augment this debug box into a button activated popout window with error handling for multiple data types, but this gets me started.

Upvotes: 0

A Bravo Dev
A Bravo Dev

Reputation: 532

First go first: Use System.Net.Http.HttpClient

When I usually request something to an API is because I need something and the API offers that to me... among a lot of other things I dont need. Hence, I only care about what I need, not about eveything it offers.

Anyway, if you need to know or log the raw content that is returned by the API, you simple get System.Net.HttpContent.ReadAsStringAsync().

PS: Thanks to attributes like JsonProperty, you can focus on what you need and how you need the entity to be

Upvotes: 1

Brian Rogers
Brian Rogers

Reputation: 129827

You could choose to use Json.Net's Linq-to-Json API instead of writing classes. Then, all parts of the JSON will be available, similar to JavaScript. For example:

string json = @"
    [
      {
        ""key"": ""WcoUC"",
        ""url"": ""https://www.shorty.com/WcoUC"",
        ""clicks"": 17,
        ""expires"": ""2017-12-22 15:30:00"",
        ""created_at"": ""2017-12-18 22:44:54"",
        ""updated_at"": ""2017-12-18 22:44:54"",
        ""redirect_to"": ""http://www.example2.com/""
      }
    ]";

JArray array = JArray.Parse(json);
foreach (JObject obj in array.Children<JObject>())
{
    foreach (JProperty prop in obj.Properties())
    {
        Console.WriteLine(prop.Name + ": " + prop.Value.ToString());    
    }
    Console.WriteLine();
}

Fiddle: https://dotnetfiddle.net/xyZvdO

Upvotes: 1

Emre Kabaoglu
Emre Kabaoglu

Reputation: 13146

If you accept the losting intellisense, you can deserialize it a dictionary or dynamic;

string json = @"{'key' : 'k', 'url' : 'u', 'clicks' : 'c' }";
var keys = JObject.Parse(json).Properties();
//Dictionary
var keysDict = keys
    .ToDictionary(
        k => k.Name,
        v => v.Value.ToString());
//Dynamic
var dynamicObject = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine(dynamicObject.key);

Upvotes: 0

Daniel A. White
Daniel A. White

Reputation: 191058

JSON.Net has a way to receive errors from the process. Specify an Error delegate in the JsonSeralizerSettings. Read about it here.

Upvotes: 1

Related Questions