Skip to the content.

Tutorial 07: JSON for Beginners

๐ŸŽฏ What Youโ€™ll Learn

๐Ÿ“š Prerequisites

๐Ÿค” What is JSON?

JSON stands for JavaScript Object Notation. Itโ€™s a way to represent data as text that both humans and computers can read.

Think of JSON like a recipe card:

Why Do APIs Use JSON?

๐Ÿ“– Reading JSON

Basic JSON Syntax

JSON has only a few simple rules:

1. Objects (Like a Dictionary)

Objects use curly braces {} and contain key-value pairs:

{
  "name": "Alice",
  "age": 30,
  "city": "New York"
}

Think of this like a form:

2. Arrays (Like a List)

Arrays use square brackets [] and contain multiple items:

[
  "apple",
  "banana",
  "orange"
]

This is just a list of fruits.

3. Values

JSON values can be:

Real API Example

Hereโ€™s what GitHubโ€™s API returns for a user:

{
  "login": "octocat",
  "id": 583231,
  "name": "The Octocat",
  "company": "GitHub",
  "location": "San Francisco",
  "email": null,
  "bio": "There once was...",
  "public_repos": 8,
  "followers": 9001,
  "following": 9,
  "created_at": "2011-01-25T18:44:36Z"
}

Letโ€™s break it down:

๐Ÿ’ป Parsing JSON in C#

Method 1: Dynamic Parsing (Quick and Easy)

Best for: Exploring APIs, prototypes, small projects

using System;
using System.Threading.Tasks;
using CurlDotNet;

class Program
{
    static async Task Main()
    {
        var result = await Curl.ExecuteAsync("curl https://api.github.com/users/octocat");

        // Parse as dynamic - no class needed!
        dynamic user = result.ParseJson();

        Console.WriteLine($"Name: {user.name}");
        Console.WriteLine($"Company: {user.company}");
        Console.WriteLine($"Followers: {user.followers}");
        Console.WriteLine($"Repos: {user.public_repos}");
    }
}

Output:

Name: The Octocat
Company: GitHub
Followers: 9001
Repos: 8

Pros:

Cons:

Method 2: Strongly Typed (Professional)

Best for: Production code, large projects, team development

using System;
using System.Threading.Tasks;
using CurlDotNet;

public class GitHubUser
{
    public string Login { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }
    public string Company { get; set; }
    public string Location { get; set; }
    public string Email { get; set; }
    public string Bio { get; set; }
    public int Public_Repos { get; set; }
    public int Followers { get; set; }
    public int Following { get; set; }
    public DateTime Created_At { get; set; }
}

class Program
{
    static async Task Main()
    {
        var result = await Curl.ExecuteAsync("curl https://api.github.com/users/octocat");

        // Parse to your class
        GitHubUser user = result.ParseJson<GitHubUser>();

        Console.WriteLine($"Name: {user.Name}");
        Console.WriteLine($"Company: {user.Company}");
        Console.WriteLine($"Followers: {user.Followers}");
        Console.WriteLine($"Repos: {user.Public_Repos}");
        Console.WriteLine($"Joined: {user.Created_At:yyyy-MM-dd}");
    }
}

Pros:

Cons:

๐Ÿ—๏ธ Creating Classes from JSON

The Easy Way: Use QuickType.io

  1. Copy the JSON response
  2. Go to quicktype.io
  3. Paste your JSON
  4. Select โ€œC#โ€
  5. Copy the generated classes!

Example: Weather API

JSON Response:

{
  "location": "London",
  "temperature": 15,
  "condition": "Cloudy",
  "humidity": 65,
  "wind_speed": 10
}

Generated C# Class:

public class Weather
{
    public string Location { get; set; }
    public int Temperature { get; set; }
    public string Condition { get; set; }
    public int Humidity { get; set; }
    public int Wind_Speed { get; set; }
}

Usage:

var result = await Curl.ExecuteAsync("curl https://api.weather.com/current");
Weather weather = result.ParseJson<Weather>();

Console.WriteLine($"It's {weather.Temperature}ยฐC and {weather.Condition} in {weather.Location}");

๐ŸŽจ Working with Nested JSON

Simple Nesting

Many APIs return nested objects:

{
  "user": {
    "name": "Alice",
    "email": "alice@example.com",
    "address": {
      "street": "123 Main St",
      "city": "Boston",
      "country": "USA"
    }
  }
}

C# Classes:

public class UserResponse
{
    public User User { get; set; }
}

public class User
{
    public string Name { get; set; }
    public string Email { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

Usage:

var result = await Curl.ExecuteAsync("curl https://api.example.com/user");
UserResponse response = result.ParseJson<UserResponse>();

Console.WriteLine($"Name: {response.User.Name}");
Console.WriteLine($"Email: {response.User.Email}");
Console.WriteLine($"City: {response.User.Address.City}");

Arrays of Objects

APIs often return lists:

{
  "users": [
    {
      "name": "Alice",
      "age": 30
    },
    {
      "name": "Bob",
      "age": 25
    },
    {
      "name": "Charlie",
      "age": 35
    }
  ]
}

C# Classes:

public class UsersResponse
{
    public List<User> Users { get; set; }
}

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Usage:

var result = await Curl.ExecuteAsync("curl https://api.example.com/users");
UsersResponse response = result.ParseJson<UsersResponse>();

foreach (var user in response.Users)
{
    Console.WriteLine($"{user.Name} is {user.Age} years old");
}

Root-Level Arrays

Sometimes the entire response is an array:

[
  {
    "id": 1,
    "title": "Buy milk"
  },
  {
    "id": 2,
    "title": "Walk dog"
  }
]

C# Class:

public class Todo
{
    public int Id { get; set; }
    public string Title { get; set; }
}

Usage:

var result = await Curl.ExecuteAsync("curl https://jsonplaceholder.typicode.com/todos");
List<Todo> todos = result.ParseJson<List<Todo>>();

foreach (var todo in todos.Take(5))  // Show first 5
{
    Console.WriteLine($"[{todo.Id}] {todo.Title}");
}

๐Ÿ“ค Creating JSON for Requests

Sending JSON in POST Requests

Many APIs require you to send JSON data:

using System;
using System.Threading.Tasks;
using CurlDotNet;

public class CreateUserRequest
{
    public string Name { get; set; }
    public string Email { get; set; }
    public int Age { get; set; }
}

class Program
{
    static async Task Main()
    {
        // Create the object
        var newUser = new CreateUserRequest
        {
            Name = "Alice",
            Email = "alice@example.com",
            Age = 30
        };

        // Convert to JSON and send
        var result = await Curl.ExecuteAsync(@"
            curl -X POST https://api.example.com/users \
              -H 'Content-Type: application/json' \
              -d '{""name"":""Alice"",""email"":""alice@example.com"",""age"":30}'
        ");

        if (result.IsSuccess)
        {
            Console.WriteLine("User created!");
        }
    }
}

Using System.Text.Json

For complex objects, use the JSON serializer:

using System;
using System.Text.Json;
using System.Threading.Tasks;
using CurlDotNet;

class Program
{
    static async Task Main()
    {
        var newUser = new
        {
            name = "Alice",
            email = "alice@example.com",
            age = 30,
            address = new
            {
                street = "123 Main St",
                city = "Boston"
            }
        };

        // Serialize to JSON
        string json = JsonSerializer.Serialize(newUser);
        Console.WriteLine($"Sending: {json}");

        // Send it
        var result = await Curl.ExecuteAsync($@"
            curl -X POST https://api.example.com/users \
              -H 'Content-Type: application/json' \
              -d '{json}'
        ");

        if (result.IsSuccess)
        {
            Console.WriteLine("User created!");
            var response = result.ParseJson<dynamic>();
            Console.WriteLine($"New user ID: {response.id}");
        }
    }
}

๐ŸŽฏ Common JSON Patterns

Pattern 1: Wrapped Response

{
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice"
  },
  "message": "User retrieved successfully"
}
public class ApiResponse<T>
{
    public bool Success { get; set; }
    public T Data { get; set; }
    public string Message { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// Usage
var result = await Curl.ExecuteAsync("curl https://api.example.com/user/123");
var response = result.ParseJson<ApiResponse<User>>();

if (response.Success)
{
    Console.WriteLine($"User: {response.Data.Name}");
}

Pattern 2: Paginated Response

{
  "items": [
    {"id": 1, "name": "Item 1"},
    {"id": 2, "name": "Item 2"}
  ],
  "page": 1,
  "total_pages": 10,
  "total_items": 100
}
public class PaginatedResponse<T>
{
    public List<T> Items { get; set; }
    public int Page { get; set; }
    public int Total_Pages { get; set; }
    public int Total_Items { get; set; }
}

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// Usage
var result = await Curl.ExecuteAsync("curl https://api.example.com/items?page=1");
var response = result.ParseJson<PaginatedResponse<Item>>();

Console.WriteLine($"Page {response.Page} of {response.Total_Pages}");
Console.WriteLine($"Total items: {response.Total_Items}");

foreach (var item in response.Items)
{
    Console.WriteLine($"- {item.Name}");
}

Pattern 3: Error Response

{
  "error": {
    "code": "INVALID_INPUT",
    "message": "Email is required",
    "field": "email"
  }
}
public class ErrorResponse
{
    public Error Error { get; set; }
}

public class Error
{
    public string Code { get; set; }
    public string Message { get; set; }
    public string Field { get; set; }
}

// Usage
var result = await Curl.ExecuteAsync("curl https://api.example.com/user");

if (!result.IsSuccess)
{
    try
    {
        var error = result.ParseJson<ErrorResponse>();
        Console.WriteLine($"Error: {error.Error.Message}");
        Console.WriteLine($"Field: {error.Error.Field}");
    }
    catch
    {
        Console.WriteLine("Unknown error format");
    }
}

๐Ÿ”ง JSON Property Naming

Handling Different Naming Conventions

APIs often use different naming styles:

API Returns:

{
  "user_name": "alice",
  "first_name": "Alice",
  "last_name": "Smith"
}

Option 1: Match the API (Ugly in C#)

public class User
{
    public string user_name { get; set; }  // Not C# style
    public string first_name { get; set; }
    public string last_name { get; set; }
}

Option 2: Use JsonPropertyName Attribute (Best)

using System.Text.Json.Serialization;

public class User
{
    [JsonPropertyName("user_name")]
    public string UserName { get; set; }

    [JsonPropertyName("first_name")]
    public string FirstName { get; set; }

    [JsonPropertyName("last_name")]
    public string LastName { get; set; }
}

Now you can use C# naming conventions in your code!

๐ŸŽฎ Complete Example: GitHub Repository Browser

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using CurlDotNet;

public class Repository
{
    public string Name { get; set; }
    public string Description { get; set; }

    [JsonPropertyName("html_url")]
    public string HtmlUrl { get; set; }

    [JsonPropertyName("stargazers_count")]
    public int Stars { get; set; }

    [JsonPropertyName("forks_count")]
    public int Forks { get; set; }

    public string Language { get; set; }

    [JsonPropertyName("created_at")]
    public DateTime CreatedAt { get; set; }
}

class Program
{
    static async Task Main()
    {
        Console.WriteLine("GitHub Repository Browser");
        Console.WriteLine("=========================\n");

        Console.Write("Enter GitHub username: ");
        string username = Console.ReadLine();

        Console.WriteLine($"\nFetching repositories for {username}...\n");

        try
        {
            var result = await Curl.ExecuteAsync(
                $"curl https://api.github.com/users/{username}/repos?sort=updated&per_page=5"
            );

            if (!result.IsSuccess)
            {
                Console.WriteLine($"Error: Could not find user '{username}'");
                return;
            }

            var repos = result.ParseJson<List<Repository>>();

            if (repos.Count == 0)
            {
                Console.WriteLine("No repositories found.");
                return;
            }

            Console.WriteLine($"Top {repos.Count} repositories:\n");

            foreach (var repo in repos)
            {
                Console.WriteLine($"๐Ÿ“ฆ {repo.Name}");

                if (!string.IsNullOrEmpty(repo.Description))
                    Console.WriteLine($"   {repo.Description}");

                Console.WriteLine($"   โญ {repo.Stars} stars | ๐Ÿ”ฑ {repo.Forks} forks | ๐Ÿ’ป {repo.Language ?? "Unknown"}");
                Console.WriteLine($"   ๐Ÿ”— {repo.HtmlUrl}");
                Console.WriteLine($"   ๐Ÿ“… Created: {repo.CreatedAt:yyyy-MM-dd}");
                Console.WriteLine();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

Example Output:

GitHub Repository Browser
=========================

Enter GitHub username: octocat

Fetching repositories for octocat...

Top 5 repositories:

๐Ÿ“ฆ Hello-World
   My first repository on GitHub!
   โญ 2341 stars | ๐Ÿ”ฑ 1234 forks | ๐Ÿ’ป Unknown
   ๐Ÿ”— https://github.com/octocat/Hello-World
   ๐Ÿ“… Created: 2011-01-26

๐Ÿ“ฆ Spoon-Knife
   This repo is for demonstration purposes only.
   โญ 12345 stars | ๐Ÿ”ฑ 140000 forks | ๐Ÿ’ป HTML
   ๐Ÿ”— https://github.com/octocat/Spoon-Knife
   ๐Ÿ“… Created: 2011-10-21

๐ŸŽ“ Key Takeaways

  1. JSON is simple - Just objects {}, arrays [], and values
  2. Use ParseJson() to convert JSON strings to C# objects
  3. Create classes that match your JSON structure
  4. Use QuickType.io to generate classes automatically
  5. Handle nested objects with nested classes
  6. Arrays become Lists in C#
  7. JsonPropertyName lets you use C# naming conventions
  8. Always handle errors when parsing JSON

๐Ÿš€ Next Steps

Now that you understand JSON:

  1. Next Tutorial โ†’ Headers Explained
  2. Practice - Parse responses from different APIs
  3. Experiment - Try creating complex nested structures
  4. Explore - Visit JSONPlaceholder for practice APIs

๐Ÿ“š Summary

JSON is the language of web APIs. Youโ€™ve learned how to:

With these skills, you can work with any JSON-based API!


Ready to learn about HTTP headers? โ†’ Headers Explained

Need help? Check the Troubleshooting Guide or ask in Discussions