1

I'm fairly new to C# at least when it comes to things like this, so I apologize for the little amount of code I have.

I have a class that called Project.cs that needs to be used to hold data objects that I get from a 3rd party API.

Here is the class:

//Project.cs

public sealed class Project
{
    public String Id { get; set; }
    public String Title { get; set; }
    public String Url { get; set; }
}

The method that you see below, is supposed to get the data(JSON) from the 3rd party API.

This API returns a list of projects in JSON form.

Fortunately I only need to pick a few attributes from the API (Id, Title, and URL).

Unfortunately, I have no idea how to get pick those specific attributes from the JSON and turn them into a collection of type Project.

Here is what I have so far. I know it's sparse.

//ProjectSearch.cs

public IEnumerable<Project> GetProjects(String catId)
{
    //Get the data from the API
    WebRequest request = WebRequest.Create("http://research.a.edu/api/Catalogs('123')");
    request.ContentType = "application/json; charset=utf-8";
    WebResponse response = request.GetResponse();

    //put each object found in the API into a Project object        
    var project = new Project();

}

So, now, I'm stuck. I don't know how to get all the objects from the API and put them into a collection of type Project. Do I need a loop? Or is there another type of way of doing?

Sample JSON from API:

{"odata.metadata":"http://research.a.edu/api/Catalogs/
$metadata#Catalogs /@Element", "odata.id":"http://research.a.edu/api/Catalogs
('123')",
"Id":"12345", "ParentID":"xxxx","Name":"Test1","Created":"1/1/2015","Modified":"2/1/2015","Deleted","0","URL":"http://yoursite/1",
('123')",
"Id":"7897", "ParentID":"xxxx","Name":"Test2","Created":"4/1/2015","Modified":"7/1/2015","Deleted","1","URL":"http://yoursite/2",
('123')",
"Id":"65335", "ParentID":"xxxx","Name":"Test3","Created":"7/1/2015","Modified":"9/1/2015","Deleted","0","URL":"http://yoursite/3"
}

I'm lost.

If anyone could clue me in, I'd be grateful.

Thanks!

SkyeBoniwell
  • 6,345
  • 12
  • 81
  • 185

2 Answers2

3

You should check on most popular JSON library for .NET: Newtonsoft JSON

Usage is pretty straightforward. This example is taken from the site:

string json = @"{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': [
    'Action',
    'Comedy'
  ]
}";

Movie m = JsonConvert.DeserializeObject<Movie>(json);

string name = m.Name;
Kędrzu
  • 2,385
  • 13
  • 22
  • Thanks, how does this work exactly? What if there are more than 1 movie in the JSON? Do you need to loop through the JSON and then add to the Movie class? Thanks! – SkyeBoniwell Sep 28 '15 at 14:31
  • 1
    Arrays are also acceptable. If you don't want to use the serialization approach, you can also manually parse JSON and use LINQ to JSON to fetch the data. – Kędrzu Sep 28 '15 at 14:37
  • So this only works on one object at a time? If the JSON contained 3 movies, I'd have to do the Movie m = JsonConvert... 3 times? thanks – SkyeBoniwell Sep 28 '15 at 14:48
  • No, then you will have i.e. `JsonConvert.DeserializeObject(json)` – Kędrzu Sep 28 '15 at 15:02
  • Oh ok, so that converts the JSON collection into a Movie object? Thanks! – SkyeBoniwell Sep 28 '15 at 15:21
1

I have two utility functions that i keep around just for this purpose (one for GET and the other for POST). It utilizes generics for the return type, so it can be used "anywhere".

    public static T RetrieveContent<T>(string url)
    {
        if (String.IsNullOrWhiteSpace(url))
            throw new ArgumentNullException("url");

        T returnValue = default(T);

        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";
            request.Accept = "application/json; charset=utf-8";
            using (WebResponse response = request.GetResponse())
            {
                if (response != null)
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        var serializer = new JsonSerializer();
                        var jsonTextReader = new JsonTextReader(reader);
                        returnValue = serializer.Deserialize<T>(jsonTextReader);
                    }
                }
            }
        }
        catch (Exception e)
        {
            string errMsg = String.Format("UtilitiesBL:RetrieveContent<T>(url). There was an error retrieving content from URL: {0}.", url);
            throw new Exception(errMsg, e);
        }

        return returnValue;

    }

    public static T RetrieveContentPost<T>(string url, string postData)
    {
        if (String.IsNullOrWhiteSpace(url))
            throw new ArgumentNullException("url");

        T returnValue = default(T);


        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            byte[] contentBytes = Encoding.UTF8.GetBytes(postData);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = contentBytes.Length;
            request.Accept = "application/json; charset=utf-8";

            // Get the request stream.
            using(Stream dataStream = request.GetRequestStream())
            {
                // Write the data to the request stream.
                dataStream.Write(contentBytes, 0, contentBytes.Length);
            }
            using (WebResponse response = request.GetResponse())
            {
                if (response != null)
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        var serializer = new JsonSerializer();
                        var jsonTextReader = new JsonTextReader(reader);
                        returnValue = serializer.Deserialize<T>(jsonTextReader);
                    }

                }
            }
        }
        catch (Exception e)
        {
            string errMsg = String.Format("UtilitiesBL:RetrieveContentPost(url, postData). There was an error retrieving content from URL: {0}.", url);
            throw new Exception(errMsg, e);
        }

        return returnValue;

    }

Using your sample from the question, your code would look like this:

public IEnumerable<Project> GetProjects(String catId)
{
    string url = String.Format("http://research.a.edu/api/Catalogs('{0}')", catId);
    return RetrieveContent<List<Project>>(url);
}
Shai Cohen
  • 6,074
  • 4
  • 31
  • 54
  • Thanks! That is a lot to digest! How would this work if my JSON contained a lot of data that I didn't need? I need to pick out all the objects but only need a few attributes each. – SkyeBoniwell Sep 28 '15 at 14:35
  • My pleasure. `serializer.Deserialize(jsonTextReader)` will map only the properties that exist in your class and ignore the others. Are there any parts of the code you would like me to expand upon? – Shai Cohen Sep 28 '15 at 14:39
  • Thanks. So would I just copy and paste this into my public IEnumerable GetProjects(String catId) method? – SkyeBoniwell Sep 28 '15 at 14:46
  • 1
    @999cm999: I added some sample code showing how to restructure your method calls. – Shai Cohen Sep 28 '15 at 15:34
  • Thanks, I really like this. It's very helpful. – SkyeBoniwell Sep 28 '15 at 15:35