JSON och API

Många program hämtar data från andra program, till exempel väderprognoser, busstider eller var en satellit befinner sig. Målet är att du ska förstå vad ett API är, och kunna hämta data i formatet JSON från ett öppet API och skriva ut delar av den.

Vad är ett API?

API står för Application Programming Interface — ett gränssnitt som gör att program kan utbyta information med varandra. I dag sker det oftast via webben: programmet skickar en förfrågan till en webbadress och får tillbaka data, oftast i formatet JSON.

JSON

JSON (JavaScript Object Notation) är standardformatet för data i de flesta nya projekt och används i nästan alla programmeringsspråk, inte bara JavaScript. JSON bygger på par av nycklar och värden (key-value):

{
  "namn": "Ada Lovelace",
  "ålder": 25,
  "ämnen": ["matematik", "programmering"]
}

Här är "namn", "ålder" och "ämnen" nycklar. Värdena kan vara text, tal, listor eller nya JSON-objekt.

Dictionary

När JSON läses in i Python blir det ett dictionary (dict) — en samling par av nycklar och värden. Du hämtar ett värde genom att skriva nyckeln inom hakparenteser.

Python · du kan ändra koden
person = {"namn": "Ada", "ålder": 25, "ämnen": ["matematik", "programmering"]}

print(person["namn"])       # Ada
print(person["ålder"])      # 25
print(person["ämnen"])      # ['matematik', 'programmering']
print(person["ämnen"][0])   # matematik – första ämnet i listan

Kom ihåg

  • En lista hittar värden med ett nummer, ett index: djur[0].
  • Ett dictionary hittar värden med en nyckel: person["namn"].
  • Nycklar som är text har citattecken, precis som alla andra strängar.

JSON-text blir ett dictionary med modulen json:

Python · du kan ändra koden
import json

text = '{"namn": "Ada Lovelace", "ålder": 25, "ämnen": ["matematik", "programmering"]}'
data = json.loads(text)
print(data["namn"])
print(data["ämnen"][1])

Hämta data från ett API

För att hämta data använder vi en färdigskriven funktion, hamta_json(adress), som hämtar JSON från en webbadress och gör om det till Python. Den finns färdig i kodrutorna här på sidan.

Som exempel hämtar vi var den internationella rymdstationen ISS befinner sig just nu. Vill du se hur svaret ser ut kan du öppna api.wheretheiss.at/v1/satellites/25544 i webbläsaren.

Python · du kan ändra koden
data = hamta_json("https://api.wheretheiss.at/v1/satellites/25544")
print(data)

Tänk på

I andra Python-miljöer brukar man använda modulen requests: data = requests.get(adress).json(). Det fungerar också här.

Uppgifter

Uppgift · Var är ISS?

Skriv ett program som hämtar ISS position från API:t ovan och skriver ut latitud, longitud och höjd över jorden på ett tydligt sätt. Titta i svaret från API:t efter vilka nycklar du behöver.

Din lösning · du kan ändra koden
data = hamta_json("https://api.wheretheiss.at/v1/satellites/25544")
# Skriv ut latitud, longitud och höjd
Visa lösningsförslag
Python · du kan ändra koden
data = hamta_json("https://api.wheretheiss.at/v1/satellites/25544")

print(f"Latitud:  {data['latitude']:.2f}°")
print(f"Longitud: {data['longitude']:.2f}°")
print(f"Höjd:     {data['altitude']:.0f} km")
print(f"Fart:     {data['velocity']:.0f} km/h")

Kör flera gånger — ISS rör sig i nästan 28 000 km/h, så positionen ändras hela tiden.

Uppgift · Var är ISS egentligen? (svår)

Latitud och longitud säger inte så mycket. Med reverse geocoding kan man ta reda på vilken plats en position motsvarar. Nominatim är ett öppet API som gör det. Skickar man in latitud och longitud,

https://nominatim.openstreetmap.org/reverse?lat=59.33&lon=18.07&format=json

får man ett svar som ser ut ungefär så här:

{
  "place_id": 166553904,
  "lat": "59.3300236",
  "lon": "18.0702676",
  "display_name": "4, Jakobs Torg, Klara, Norrmalm, Stockholm, Stockholms kommun, Stockholms län, 111 74, Sverige",
  "address": {
    "house_number": "4",
    "road": "Jakobs Torg",
    "suburb": "Norrmalm",
    "city": "Stockholm",
    "county": "Stockholms län",
    "postcode": "111 74",
    "country": "Sverige",
    "country_code": "se"
  }
}

Kombinera de två API:erna: hämta ISS position och ta reda på vad som finns under stationen just nu. Tänk på att ISS ofta är över havet, och då hittar Nominatim ingen adress alls. Prova adressen ovan med lat=30 och lon=-40 (mitt i Atlanten) i webbläsaren — vad svarar API:t då?

Din lösning · du kan ändra koden
# Skriv din kod här
Visa lösningsförslag
Python · du kan ändra koden
iss = hamta_json("https://api.wheretheiss.at/v1/satellites/25544")
lat = iss["latitude"]
lon = iss["longitude"]
print(f"ISS är på latitud {lat:.2f}, longitud {lon:.2f}")

adress = f"https://nominatim.openstreetmap.org/reverse?lat={lat}&lon={lon}&format=json&accept-language=sv"
plats = hamta_json(adress)

# Hittar Nominatim ingen plats innehåller svaret nyckeln "error"
if "error" in plats:
    print("Där finns ingen adress – ISS är förmodligen över ett hav.")
else:
    print(f"Under ISS just nu: {plats['display_name']}")

Snabbkoll

Har du förstått?

1.Vad står API för?

2.Hur skriver du ut ”programmering” ur person = {"ämnen": ["matematik", "programmering"]}?

3.Vad är skillnaden mellan en lista och ett dictionary?