People in Space! (2023 .NET Advent)

5 minute read article dotnet   microsoft   advent   spectre.console   csharp Comments

Note: This post is part of the 2023 .NET Advent! Check out the rest of the entries!. Last week I published my entry for the C# Advent which you can find here.

This year’s post will be relatively simple, but also fun and interesting. I’m going to dive back into Brian’s “Exercises for Programmers” one more time and build a very small console application using C# and Spectre.Console that consumes an API and displays the data it returns.

Some background

There are currently a little over 8 billion people on the planet, and that number grows every day. It is projected that by 2037, we’ll hit 9 billion, and 10 billion by 2058. Those numbers are staggering considering that in 1974 (two years after I was born), the population was only 4 billion! See Worldometer for more information.

Consider that of 8 billion humans alive today, a handful are NOT living on the planet. Wikipedia has the following statistics about space travel:

As of May 2022, people from 44 countries have traveled in space. As of July 2022 570 have reached the altitude of space according to the FAI definition of the boundary of space, and as of June 2023 656 people have reached the altitude of space according to the USAF definition and 606 people have reached Earth orbit. 24 people have traveled beyond low Earth orbit and either circled, orbited, or walked on the Moon.

It’s unfortunate that space travel really doesn’t have the public eye like it once did. Sure, SpaceX, Blue Origin and the potential of commercial space flight is interesting, but the excitement around that doesn’t compare to the space race of the 1960s or even the shuttle missions of the 80s.

For those who have seen the Earth from space, and for the hundreds and perhaps thousands more who will, the experience most certainly changes your perspective. The things that we share in our world are far more valuable than those which divide us.

This is a sentiment I’ve seen shared time and time again by the brave men and women who have left the confines of our planet, whether it was to orbit the earth in a tiny capsule, go to the moon, or spend time in the shuttle or on the space station. In the spirit of the holidays and of the upcoming New Year, I want us all to take a break from the hate and vitriol that is so easily spewed online and instead focus on the things we have in common. Our problems really do seem small when you consider that we are living on a tiny blue marble in the vastness of space.

The Problem

From Brian’s book, the exercise states:

Visit http://api.open-notify.org/astros.json to see not only how many people are currently in space but also their names and which spacecraft they’re on. Create a program that pulls in this data and displays the information from this API in a tabular format.

The code I’m going to write reads from an API written and maintained by Nathan Bergey. While the API hasn’t been touched in many years, he maintains the data, so the information that’s retrieved is current, at least as of December 18, 2023.

Step one, of course, is to create a new console application and add Spectre.Console.


dotnet new console -o peopleInSpace
cd peopleInSpace
dotnet package add Spectre.Console

There’s no input required for this program, only querying the API and displaying the results. Before doing that, the default output needs to change from “Hello, World!” to something more appropriate, so


Console.WriteLine("People in Space!");

In my GenX head, I hear the narrator from The Muppet Show saying, “Piiiigggss innnnn Spaaaaaace!” and now you’re welcome for this clip from the show with Mark Hamill as Luke Skywalker!

On with the code. The data we need can be found here:


http://api.open-notify.org/astros.json

The result will look like this:

{
  "message": "success",
  "number": NUMBER_OF_PEOPLE_IN_SPACE,
  "people": [
    {"name": NAME, "craft": SPACECRAFT_NAME},
    ...
  ]
}

The class we’ll deserialize into is straightforward:


public class Payload
{
  public string Message { get; set; }
  public int Number { get; set; }
  public List<Person> People { get; set; }
}

public class Person
{
  public string Name { get; set; }
  public string Craft { get; set; }
}

HttpClient makes it really simple to retrieve the data, and we’ll use System.Text.Json for deserialization. Note the option to ignore case when deserializing.


var client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://api.open-notify.org/astros.json");
if (response.IsSuccessStatusCode)
{
    string content = await response.Content.ReadAsStringAsync();
    var peopleInSpace = JsonSerializer.Deserialize<Payload>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

    Console.WriteLine($"There are currently {peopleInSpace!.Number} in space!");
}

While I could simply iterate overe the list of People and output directly to the console, I’ll throw in Spectre.Console, specifically a Table. Since the table has a Title, I also removed the first Console.WriteLine.


var table = new Table
{
    Title = new TableTitle("People in Space!")
};

table.AddColumn("Person");
table.AddColumn("Craft");

AnsiConsole.Write(table);

A simple foreach will get us started on displaying the people and what craft they’re on since there may be times people are on the ISS AND in craft traveling to or from the space station, or maybe missions from other countries that don’t involve the ISS.


    foreach(var person in peopleInSpace!.People)
    {
        table.AddRow(person.Name, person.Craft);
    }

The output should look something like this:

Output

Here is the final code:


using System.Text.Json;
using Spectre.Console;

var table = new Table
{
    Title = new TableTitle("People in Space!")
};

table.AddColumn("Person");
table.AddColumn("Craft");

var client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://api.open-notify.org/astros.json");
if (response.IsSuccessStatusCode)
{
    string content = await response.Content.ReadAsStringAsync();
    var peopleInSpace = JsonSerializer.Deserialize<Payload>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

    foreach(var person in peopleInSpace!.People)
    {
        table.AddRow(person.Name, person.Craft);
    }

    AnsiConsole.Write(table);
    Console.WriteLine($"There are currently {peopleInSpace!.Number} in space!");
}


public class Payload
{
  public string Message { get; set; } = string.Empty;
  public int Number { get; set; }
  public List<Person> People { get; set; } = new();
}

public class Person
{
  public string Name { get; set; } = string.Empty;
  public string Craft { get; set; } = string.Empty;
}

Like I said at the beginning, it’s pretty simple. Brian did have some challenges like ensuring a given craft is only listed once in the output, and order the people by their last name. With the data coming back on December 18, 2023, I could easily handle both of those with some LINQ, but I’ll leave those for another time.

And with that, another Advent post is done, and I’m happy with the code I wrote. I hope you enjoyed this post!

Make sure you check out the code on GitHub!


A seal indicating this page was written by a human

Updated:

Comments