Parseando JSON con Golang y las naves de spaceX
Golang se ha convertido en uno de mis lenguajes favoritos y hoy escribiré de como podemos usar go para poder consumir la API de spaceX y obtener información de las naves lanzadas al espacio
Soy admirador total de Elon musk y de todas sus compañías, una de ellas es spaceX, una compañía dedicada al transporte aeroespacial y hoy por medio de Golang vamos a obtener información de su ultima nave lanzada al espacio.
SpaceX provee una API para obtener toda la información de las naves lanzadas al espacio:
curl -x https://api.spacexdata.com/v3/launches/latest | jq .
Con esta API podemos obtener los siguientes datos:
{
"flight_number": 74,
"mission_name": "Iridium NEXT Mission 8",
"mission_id": [
"F3364BF"
],
"launch_year": "2019",
"launch_date_unix": 1547220660,
"launch_date_utc": "2019-01-11T15:31:00.000Z",
"launch_date_local": "2019-01-11T07:31:00-08:00",
"is_tentative": false,
"tentative_max_precision": "hour",
"tbd": false,
"launch_window": 0,
"rocket": {
"rocket_id": "falcon9",
"rocket_name": "Falcon 9",
"rocket_type": "FT",
"first_stage": {
"cores": [
{
"core_serial": "B1049",
"flight": 2,
"block": 5,
"gridfins": true,
"legs": true,
"reused": true,
"land_success": true,
"landing_intent": true,
"landing_type": "ASDS",
"landing_vehicle": "JRTI"
}
]
},
"second_stage": {
"block": 5,
"payloads": [
{
"payload_id": "Iridium NEXT 8",
"norad_id": [
43922,
43923,
43924,
43925,
43926,
43927,
43928,
43929,
43930,
43931
],
"reused": false,
"customers": [
"Iridium Communications"
],
"nationality": "United States",
"manufacturer": "Thales Alenia Space",
"payload_type": "Satellite",
"payload_mass_kg": 9600,
"payload_mass_lbs": 21164.38,
"orbit": "PO",
"orbit_params": {
"reference_system": "geocentric",
"regime": "low-earth",
"longitude": null,
"semi_major_axis_km": 6997.303,
"eccentricity": 0.0011185,
"periapsis_km": 611.342,
"apoapsis_km": 626.995,
"inclination_deg": 86.6809,
"period_min": 97.085,
"lifespan_years": 15,
"epoch": "2019-01-14T19:01:22.000Z",
"mean_motion": 14.83223805,
"raan": 46.2409,
"arg_of_pericenter": 203.1527,
"mean_anomaly": 156.9184
}
}
]
},
"fairings": {
"reused": false,
"recovery_attempt": false,
"recovered": null,
"ship": null
}
},
"ships": [
"JRTI-2",
"NRCQUEST",
"PACIFICFREEDOM"
],
"telemetry": {
"flight_club": "https://www.flightclub.io/result?code=IRD8"
},
"launch_site": {
"site_id": "vafb_slc_4e",
"site_name": "VAFB SLC 4E",
"site_name_long": "Vandenberg Air Force Base Space Launch Complex 4E"
},
"launch_success": true,
"links": {
"mission_patch": "https://images2.imgbox.com/80/ae/1JL1ZzXD_o.png",
"mission_patch_small": "https://images2.imgbox.com/11/f0/xPDcIpmS_o.png",
"reddit_campaign": "https://www.reddit.com/r/spacex/comments/a699fh/iridium_next_constellation_mission_8_launch/",
"reddit_launch": "https://www.reddit.com/r/spacex/comments/aemq2i/rspacex_iridium_next_8_official_launch_discussion/",
"reddit_recovery": "https://www.reddit.com/r/spacex/comments/aewp4r/iridium_8_recovery_thread/",
"reddit_media": "https://www.reddit.com/r/spacex/comments/aeoxve/rspacex_iridium_next_8_media_thread_videos_images/",
"presskit": "https://www.spacex.com/sites/spacex/files/iridium8presskit.pdf",
"article_link": "https://spaceflightnow.com/2019/01/11/spacex-begins-2019-with-eighth-and-final-for-upgraded-iridium-network/",
"wikipedia": "https://en.wikipedia.org/wiki/Iridium_satellite_constellation#Next-generation_constellation",
"video_link": "https://youtu.be/VshdafZvwrg",
"youtube_id": "VshdafZvwrg",
"flickr_images": [
"https://farm5.staticflickr.com/4866/39745612523_14270b4b9d_o.jpg",
"https://farm8.staticflickr.com/7833/39745612923_21aa442350_o.jpg",
"https://farm5.staticflickr.com/4881/39745613173_e99b09c000_o.jpg",
"https://farm8.staticflickr.com/7882/39745613513_6cdd4581af_o.jpg",
"https://farm8.staticflickr.com/7807/39745613733_1a7b70e54a_o.jpg",
"https://farm5.staticflickr.com/4891/39745614053_43855205bc_o.jpg"
]
},
"details": "SpaceX's first flight of 2019 will be the eighth and final launch of its planned Iridium flights. Delivering 10 satellites to low earth orbit, this brings the total up to 75 and completes the Iridium NEXT constellation. This mission launches from SLC-4E at Vandenberg AFB. The booster is expected to land on JRTI.",
"upcoming": false,
"static_fire_date_utc": "2019-01-06T13:51:00.000Z",
"static_fire_date_unix": 1546782660,
"timeline": null
}
Pero no queremos toda la información que nos da el API, solo queremos saber, estos tres valores: Number Flight, mission Name y description. para esto, usaremos Go y consumiremos la API.
Pre-requisitos
- Instalar Go desde https://golang.org/dl/
- Chequear la instalación de Go con go version // Yo estoy utilizando la version 1.9.1
- Para este caso utilizare librerías estándares de Go, ya que tiene los componentes de HTTP y JSON necesarios.
- Pueden utilizar el editor de texto que quieran, yo utilizo vim con el plugin go-vim
creamos un archivo llamado spaceX.go y escribimos las lineas básicas de nuestro archivo:
package main
func main() {
}
podemos ejecutar nuestro archivo como go run spaceX.go o go build ./spaceX.go
Ahora crearemos el request hacia la API y parsearemos el output para tener los valores que necesitamos:, para eso necesitamos los siguientes librerías
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
Tambien necesitamos escribir una estructura donde se extraera el texto del JSON, el nombre de las propiedades de la estructura deben iniciar con una letra mayúscula, para que puedan ser referenciadas como publicas
type ship struct {
Flight_number int `json:"flight_number"`
Mission_name string `json:"mission_name"`
Details string `json:"details"`
}
Realizamos el request y leemos la data con ioutil.ReadAll
url := "https://api.spacexdata.com/v3/launches/latest"
spaceX := http.Client{
Timeout: time.Second * 2,
}
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Fatal(err)
}
res, getErr := spaceX.Do(req)
if getErr != nil {
log.Fatal(getErr)
}
body, readErr := ioutil.ReadAll(res.Body)
if readErr != nil {
log.Fatal(readErr)
}
Instanciamos ship1 con base a la estructura ship que escribimos anteriormente, posteriormente usamos json.Unmarshal para encodear la data y almacenarla en el objeto que instanciamos
<pre class="wp-block-code"><code> ship1 := ship{}
jsonErr := json.Unmarshal(body, &ship1)
if jsonErr != nil {
log.Fatal(jsonErr)
}
Por ultimo el resultado final que queremos mostrar:
fmt.Println("Flight Number: ", ship1.Flight_number)
fmt.Println("Mission Name: ", ship1.Mission_name)
fmt.Println("Details: ", ship1.Details)
Nuestro código debe quedar algo asi:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
type ship struct {
Flight_number int `json:"flight_number"`
Mission_name string `json:"mission_name"`
Details string `json:"details"`
}
func main() {
url := "https://api.spacexdata.com/v3/launches/latest"
spaceX := http.Client{
Timeout: time.Second * 2,
}
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Fatal(err)
}
res, getErr := spaceX.Do(req)
if getErr != nil {
log.Fatal(getErr)
}
body, readErr := ioutil.ReadAll(res.Body)
if readErr != nil {
log.Fatal(readErr)
}
ship1 := ship{}
jsonErr := json.Unmarshal(body, &ship1)
if jsonErr != nil {
log.Fatal(jsonErr)
}
fmt.Println("Flight Number: ", ship1.Flight_number)
fmt.Println("Mission Name: ", ship1.Mission_name)
fmt.Println("Details: ", ship1.Details)
}
Guardamos y ejecutamos y debemos obtener un output como este:
Flight Number: 74
Mission Name: Iridium NEXT Mission 8
Details: SpaceX's first flight of 2019 will be the eighth and final launch of its planned Iridium flights. Delivering 10 satellites to low earth orbit, this brings the total up to 75 and completes the Iridium NEXT constellation. This mission launches from SLC-4E at Vandenberg AFB. The booster is expected to land on JRTI.
Con esto, logramos escribir con Go un HTTP Client que realiza un Request para consumir la API de spaceX y obtener un poco de información de la ultima nave lanzada al espacio.
Mas información