CONSUMIENDO UNA API EN JAVA EN UN ABRIR Y CERRAR DE OJOS: LA HISTORIA

   

"...había logrado consumir una API en java pero no sabia nada"

PARTE I: El inicio

    El otro día mientras realizaba un Challenge del Programa ONE me choque contra un muro... 

    Había visto que algunos compañeros había implementado una API a sus programas en Java y me pareció algo maravilloso, así que me dije "quiero hacer lo mismo". Entonces, empecé a ver tutoriales en YouTube de como hacerlo, muchos eran buenos, otros no tanto, lo cierto es que entre videos y videos logré mi cometido: consumir una API en Java.

    Pero ahora en mi mente surgían algunas preguntas "¿Por que debo usar esta clase en especifico?", "¿Por que es tan largo este procedimiento? ¿No podría ser mas fácil?" Y ahí me di cuenta de la realidad, había logrado consumir una API en java pero no sabia nada.

    Me preguntaba: "¿A cuentas personas le habrás pasado lo mismo que a mi?" Así que me decidí escribir mi experiencia en primer plano de como voy aprendiendo a consumir una Api en Java para hacerlos llorar y que sientan pena por mi, jajaja nah, en realidad, mi intención es tener una "especie" de documentación o anotaciones que me sirva como material de consulta y que también le pueda servir a alguien mas.

    Ante de comenzar con este articulo, quiero dejar en claro que no soy ningún experto en la materia, por lo tanto, si encuentra algún error de conceptos o ideas, por favor, hazlo saber enviando tu explicación junto con la documentación técnica. Además. durante las explicaciones es posible que use un lenguaje coloquial en vez de lenguajes técnico, pues la idea es entender forma sencilla a grandes rasgo ciertas ideas o conceptos.

El famoso Http y la hermosa API

    Al darme cuenta de mi realidad, empecé a tomar carta en el asunto. Lo primero que hice fue cuestionarme sobre que es lo que sabía de las API's y como ya les mencioné no sabía nada o casi nada, así que empecé a ver cual era esquema de una api y eso me llevó a tratar de entender un poco que es un Http y que es una Api.

    Es posible que a estas altura te pregunte '¿Por que es importante conocer este tema?' Como futuros programadores es necesario conocer -al menos en forma general- el esquema de comunicación entre un cliente y un servidor. Así que debemos conocer algo sobre el Http y también sobre las Api's.

¿Qué es el Http?

    La primera pregunta que debía responder era "¿Qué era un Http?" así  fue que llegué a la definición de que  un HTTP (Hypertext Transfer Protocol) no es más que un protocolo que contiene un conjuntos de reglas que permite realizar una petición de datos y recursos. Este protocolo esta basado en el principio de cliente-servidor donde las peticiones son realizada por el cliente (también llamado agente de usuario) que puede ser desde un navegador web hasta cualquier otro programa como una app o cualquier otra cosa que haga la misma función. Y el servidor web se encarga de gestionar dichas peticiones y responderla.

    Por eso se puede decir que el Http es la base de la www porque es un protocolo que  permite la transferencia de datos usando enlaces de hipertexto y eso nos permite navegar entre páginas.


    El Http cuenta con métodos para realizar solicitudes como, por ejemplo, GET, POST, PUT y DELETE. Si quieres saber mas sobre estos métodos puedes visitar la siguiente documentación: https://developer.mozilla.org/es/docs/Web/HTTP/Methods

¿Y una API que es?

    API es una abreviatura de Application Programming Interfaces  y si no eres gringo (como yo) te hará bien saber que traducido significa interfaz de programación de aplicaciones. Son un conjunto de definiciones y protocolos que se utiliza para desarrollar e integrar el software de las aplicaciones, permitiendo la comunicación entre dos aplicaciones de software a través de un conjunto de reglas. ¿Te suena muy parecido al Http? Bueno, por lo menos a mi me sonaba parecido al principio.

¿Serán lo mismo una API y un HTTP?

    No, una API no es lo mismo que un HTTP. Una API es una interfaz de programación de aplicaciones, que como se ha dejado saber, permite la comunicación entre diferentes aplicaciones; es la "puerta" que permite que dos o mas "trozos" de software se comuniquen entre sí. Un HTTP es un protocolo (conjuntos de reglas) de transferencia de hipertexto que permite la comunicación entre un servidor web y un navegador web. Pero hay que tener el cuenta también, que una API puede usar HTTP u otros protocolos para establecer la interacción o comunicación.

    En forma de ilustración, he "creado" esta obra de arte, este esquema, que ilustra  en forma general la estructura de una API REST:

La petición (request, en inglés) se realizan por medio de métodos como, por ejemplo, GET, POST, PUT Y DELETE. Y el servidor devolverá una respuesta (response) en formato JSON o XML si la solicitud fue respondida de forma exitosa.

    Algo que no se puede olvidar es que cuando se realiza una petición al servidor, este devuelve una respuesta que contiene un código de estatus que indica si la respuesta fue exitosa o no. Por ejemplo:

200: la solicitud fue respondida de forma exitosa.
301: la solicitud fue movida permanentemente.
401: la solicitud no fue autorizada por el servidor.
404: la solicitud no fue encontrada por el servidor.
500: error interno del servidor.

PARTE II: El consumo de API

    En muchas ocasiones, cuando se habla de Api he escuchado a muchos programadores en YouTube hablar de un tal "endpoint"... endpoint para allá y  endpoint para acá; así que me surgió la necesidad de saber que era eso y tenía que saberlo porque era un termino muy sonado cuando se trataba de consumir o crear APi's, así que pensé que debía ser muy importante conocerlo antes de adentrarme al mundo de las API's.

Conociendo al Señor "endpoint"...

    Después de tanto leer en internet, encontré la respuesta de que era un "endpoint". Un “endpoint” o punto final es un el punto de contacto entre un servicio web y el internet. Pero el significado es más conciso en mundo de la programación: un endpoint es una URL de una API o un backend que responde a una petición, es decir, es una ubicación donde se envía peticiones y así obtener respuestas o la información que esta en dicha ubicación. También están los “entrypoint” pero que no hablaré de eso en este articulo; puedes revisar este enlace si quiere con conocer un poco la relación entre el “entrypoint” y el “endpoint”: 

    Ahora sí, creo que estoy listo para consumir una API en Java como todo un profesional  ¿no creen?

¿Cómo consumir una API en Java?

    No tan rápido... Al principio les mencioné sobre que logré consumir una API pero que no entendía nada, por ejemplo, no entendía del todo el porque se usaba las clases que se usaban... solo me limite a copiar y repetir código. Pero corregí mi error, ahora tengo una idea de porque se utilizan ciertas clases en Java para consumir una API; trataré de explicarlo a ver si me salen las ideas.

    Para consumir una API en java (jdk 8) es necesario utilizar la Clase abstracta HttpURLConnection y algunas librerías externas para manipular objetos json. La clase HttpURLConnection extiende o hereda de la clase abstracta URLConnection que nos sirve para examinar las propiedades del recurso especificado por la URL o para examinar el contenido de la URL, es decir, leer el contenido del recurso o web pero no nos permite enviar parámetros o modificar ciertos atributos de la conexión, atributos como, por ejemplo, el establecer el método de petición de la conexión (si es GET o POST) y para poder hacerlo necesitamos un objeto del tipo HttpURLConnection ¿por que? Porque nos brinda ciertas funcionalidades especifica para URL HTTP ¿Pero como podemos usar o instanciar un objeto de la clase HttpURLConnection si es una clase abstracta?  Bueno, podemos usar el método openConnection( ) de clase URL que nos retorna un objeto que representa la conexión del tipo URLConnection, y este objeto conexión nos sirve de “puente” entre nuestra aplicación (cliente) y el recurso referenciado por la URL (objeto URL), lo que nos permite leer, escribir u obtener información sobre el archivo o página.

    Ahora toca entender un poco los pasos para consumir una API.

Entendiendo lo pasos para consumir una API...

    1- El primer paso es crear un objeto URL porque usaré un endpoint y un endpoint es una URL.
    2- Quiero examinar el recurso que nos brinde la API para eso necesito conectarme con ella ¿Cómo lo hago? Teniendo en cuenta que necesito un objeto que represente la conexión para poder enviar o modificar propiedades de la conexión, usaré el método openConnection( )  y teniendo en cuenta además que la URL usa el protocolo Http lo más conveniente es que use HttpURLConnection porque me proporciona métodos específicos para una Url Http. Así que en resumidas cuentas necesitamos un objeto conexión del tipo HttpURLConnection.
    3- Establezco el método de conexión Http de acuerdo a la operación que deseo utilizar (usaré GET) ¿por que debo establecer el método de conexión? porque es el protocolo de comunicación exigido para realizar una petición web y al final de cuentas eso es lo que estoy haciendo al consumir una API.
    4- Con el método openConnection() he dicho con anterioridad que obtenemos una representación de la conexión que nos sirve para modificar ciertas cosas de la conexión pero no es la conexión real, para obtener la conexión real debo hacer uso del método heredado connect( ) de la clase HttpURLConnect.
    5- Si la conexión es exitosa, entonces, quiero leer el recurso que he recibido de la API ¿Y como lo leo? Bueno, hay que tener en cuenta que cuando se envía un objeto vía remota o por la red se aplica la serialización, es decir, lo que se envía es un flujo de bytes así que lo que recibo es un flujo de bytes ¿Y como leo el flujo de bytes que he recibido? Puedo usar el método openStream( )  de la clase URL que devuelve un flujo bytes de entrada para leer y podemos leerlo con Scanner e ir construyendo una cadena o string… Pero en realidad eso solo me serviría para mostrarlo por consola como una cadena del tipo string más. Y lo que necesito es manipular el objeto JSON que me devuelve la API para poder usarla a mi conveniencia, en ese sentido, debo convertir esa cadena de caracteres en un objeto JSON y ahí entra en juego librerías como Gson, Jackson o json-simple, entre otras.

PARTE III: Mano a la  obra...

    Ahora, ya estamos en capacidad para echar mano al código:

1. Crear un objeto URL

    Tomaré una Api que he sacado de la página https://www.netveloper.com/api-gratuita-para-pruebas para crear el objeto URL.


2. Obtenemos un objeto conexión del tipo HttpURLConnection

3. Establecemos el método Http "GET" para la conexión


4. Establecemos la conexión real 

    Además de establecer la conexión, también guardo en una variable el estatus que me devuelve el servidor para luego usarlo en una condición.


    Bueno esos son los pasos principales para consumir una API sencilla. Lo demás que sigue es lo habitual a la hora de manipular flujos de bytes  y el manejo de excepciones, por lo tanto, creo que no es necesario explicarlo ¿o si? bueno ya se verá... También es bueno aclarar que ya a partir de java 9 hay una API llamado HttpClient que me sirve para crear un cliente Http y consumir una Api, pero como estoy usando jdk 8, toca hacerlo así.

    El código quedaría algo así: 


    A ya qui tengo el resultado:


    ¡Lo he logrado! Ya soy todo un senior...  si si lo sé no es la gran cosa consumir una API, esto es solo el comienzo...  pero no importa  ¡Vamos con todas!  

PARTE IV: Doblegando al JSON


    El consumir una api -ahora que lo pienso- no fue lo más difícil, ¿por que? por que aun me faltaba ciertas cosas para lograr mi cometido, que en todo caso, era implementar una api a mi aplicación. La pregunta a contestar ahora era "¿Cómo la manipulo? Necesito que esto me bote los valores que voy a usar en mi aplicación", eso fue lo que pensé en aquel momento cuando por primera vez consumí una API...  Sí, otra vez tenía que indagar sobre el tema, ahí fue que me enfrente a uno de mis peores temores: al JSON.

    Claro, sabía que el JSON es usado en casi todas las aplicaciones y que eso ya por sí lo hacía muy importante, pero ya saben, pensaba que "solo iba a verlo de lejitos" y que "nunca me va a tocar crearlo" cuando estuviera ya en la industria trabajando como todo un dev, así que nunca le preste mucha atención, "él por allá y yo por aquí"; pero ahora la cosa era distinta: tenia que manipular un JSON en java.

El cuento

    Mi temor era por que en realidad veía al JSON como una estructura de texto muy larga, veía comillas "", llaves "{", corchetes "[", etc., por supuesto, entendía más o menos los datos que contenía un json pero el problema estaba en su estructura, para mí era como un "monstruo". Entonces, recordé unas palabras de un profesor que me dio clases cuando estudiaba una carrera en la universidad. La asignatura que impartía aquel profesor era algo difícil para muchos y había que resolver muchos problemas de indoles de la física... él decía: "¿Ustedes ven este problema como un monstruo, verdad? Hagan de cuenta que tienen que pelear con alguien mas grandes que ustedes. Ustedes lo ven como un monstruo, entonces, ¿Qué hacen? Usted lo golpea en la barriga, sacándole el aire, él se dobla y cae en suelo.. y ahí ustedes le caen a patadas. De la misma forma, ustedes ven a este problema así: grande, solo hay que saber atacarlo..." A claro que con este cuento no quiero incentivarlo a la violencia, para nada... entonces ¿Cuál es el punto?

    El punto es que hay saber cual es la "debilidad" del problema, saber atacarlo, lo que se traduce en conocer más a fondo los detalles del problema... Y yo debía conocer más a fondo lo que era un JSON y cómo manipularlo.

Conociendo al enemigo: al JSON

    Ya basta de chalanería y hablemos sobre que es un JSON.

    Un JSON es un formato de texto que sirve para intercambiar información y que posee una estructura organizada basada en la sintaxis de Objetos JavaScript, de hecho, su acrónimo quiere decir JavaScript Object Notation, que traducido es Notación de Objeto de JavaScript. 

   ¿Y como es su estructura? Bueno, un objeto JSON debe comenzar con llave "{" y debe finalizar con llave "}" y adentro esta su contenido que mayormente es una colección de pares clave-valor. Cuando se escribe el nombre de un atributo (clave) o el valor es string, se debe usar comillas dobles. También es posible asignar como valor de un atributo un array o asignarle otro objeto. Veamos un ejemplo mas gráficos de estos detallitos:

    ¿Y como sería en caso de que fuera un arreglo de objetos JSON? ¿Y si le quiero asignar un arreglo de objeto a mi clave en vez de un "solitario" string, se puede hacer?

    Creo que esta ilustración puede ayudar a disipar aun más las dudas:



Enfrentándome al JSON

    Después de haber comprendido un poco sobre que es un JSON y su estructura,  había llegado momento de enfrentarme con él, pero no podía hacerlo con mis manos vacía, necesitaba el poder de las Librerías, en mi caso usé la json-simple ¿por que? no lo se , fue la primera que usé, pero sé que hay otras que quizás son mas sencilla, lo importante aquí es saber el uso básico de la librería que se escoja. Está librería (json-simple) posee ciertas herramientas que esta basada en java y que nos permite convertir un objeto Java a JSON (codificar) y viceversa (decodificar); esta librería es ligera por que proporciona pocas clases, solo posee las necesarias.

    Usaré la clase JSONObject o  tal vez la clase JSONArray, todo dependerá de la estructura que nos devuelva la API. La clase JSONObject nos permite tener una representación de un objeto json. Y la clase JSONArray nos permite tener una representación de un array de objetos json. 

    Ahora, lo único que me queda es lanzarme con todo contra el JSON.

    Como la idea es también mostrar como manipular un JSON que nos "devuelve" la API, usaré la misma api que usé unas cuantas líneas atrás.

    El primer paso es ver que estructura JSON me devolvió la API. La api que usé me devolvió una estructura de un objeto JSON, por lo tanto, ¿Qué clase uso, la JSONObject o la JSONArray? Es evidente, la  clase JSONObject ¿Cómo lo sé? por que si lo recuerdan solo tiene llaves, una llave "{" que están al principio y  otra que está al final "}"; no tiene corchete "[ ]" lo que indica que no es un array de objetos... ¿ya recuerdan? si no van a tener que subir para volver a ver la imagen del resultado que me había devuelto la api, naahh mentira, aquí le pongo un trozo de la imagen:


    Este es el JSON que nos devuelve la api, así se ve mejor ¿no les parece? échenle un vistazo e imaginen que quiero obtener la dirección (address) ¿Cómo lo hago?

Autor: netveloper.com

    Voy a crear un objeto JSONParser y así poder "parsear" o analizar un string  que tiene la estructura de un JSON  ¿Por que quiero "pasear" un string o crear un analizador? para así poder leer o analizar la estructura por partes y extraer los valores que necesito y utilizarlos a mi conveniencia. Para eso, utilizaré el método parse( ) y le pasaré como argumento la cadena infoString, lo cual me devolverá un objeto que le aplicaré un "casteo" del tipo JSONObject y así lograr manipular al JSON.:


        Vamos a pintar por consola el resultado de lo que he hecho:


    El resultado aparentemente es el "mismo" visualmente a como cuando pintamos o imprimimos anteriormente la cadena infoString. Pero en este caso no es una cadena si no un objeto JSON que podemos manipular a nuestro favor. ¡Probemos esto a ver si tengo razón! 

    Hmm... quiero obtener solamente el atributo dirección (address) del objeto json ¿Cómo lo hago? Creo que hay un método get( ) que me devolverá el valor de la clave "address" pero ¿Qué tipo de dato es el valor, es decir, es un number, un string, un array o un objeto? Por el resultado visto por consola es un objeto, por tanto, tengo que almacenarlo en una variable del tipo JSONObject.

    Voy a crear una variable que llamaré "jsonObj2" del tipo JSONObject  y le asignaré el objeto que me retornará el método get( )  de la clase JSONObject  y luego lo imprimiré por consola para ver que me devolverá: 



    Nada mal ¿eh? He obtenido el valor de clave "adddress" que es un objeto. 

Esto no se ha acaba hasta que se acaba...

    "Ahora, ¿Dime quién manda JSON? jajaja wow, la verdad es que no era tan difícil vencerlo"...   Así fue que pensé cuando en su momento logré manipular el JSON y obtener algunos resultados, me sentía invencible.... pero ¿Realmente había logrado doblegar al JSON? No, pude darme cuenta de eso cuando tenia la necesidad de tener una especie de lista para mi aplicación del Challenge basada en los valores de cierta clave. Para que me puedan entender, volvamos nuestra api, la que estamos usando en este articulo y tengamos presente todo lo que hemos hecho con ella.

    Para que tengan una idea, imaginen que quiero obtener una lista de todas las claves (keys), solamente las claves del objeto que es valor de la clave "address" para después iterar sobre ella y utilizar la lista para un menú de una aplicación o para cualquier otra cosa ¿Cómo lo hacen?¿Sería posible hacerlo?... Bueno, eso es  precisamente lo que quería hacer en aquel entonces con el JSON que me retornaba el servidor.

    Trataré de hacer eso en un momento con el json que tengo ahora mismo y que ya le he mostrado. Estas son las claves que quiero obtener en una lista: 


    ¿Es posible hacerlo?...

   
    Como ya les mencioné, eso (el querer hacer una lista de keys) fue lo que hizo que me diera cuenta de que aun no había "doblegado" del todo al "JSON", aun estaba oponiendo resistencia... Había logrado manipularlo un poco pero aun me falta hacer más para poder "obligarlo" a que hiciera lo que quisiera, en mi caso: la lista de claves (keys). Hay que decirlo, esto no se había acabado aun.

PARTE V: El final

    Habían pasado varios días desde aquel momento en que quería realizar una lista para mi aplicación, había buscado todo tipo de información al respecto pero sin ningún resultado, pero un día, un día todo cambió, sí, aunque suene a cliché. Había encontrando una información en inglés que más o menos trataba lo que estaba buscando, lo percibí porque entendí un poco el código que ahi estaba , no por que supiera ingles... Después de traducir la página y devorar toda aquella información, había encontrado lo que buscaba. ¿Qué fue lo que encontré exactamente? Déjame y les explico.

    Lo que había encontrado era información referente a un método, el método keySet( ) de la clase HashMap. Este método devuelve un Set (colección) de las keys (claves) de un HashMap (estructura clave-valor) ¿Y que es nuestro objeto? Es un HashMap o "diccionario", es decir, nuestro objeto contiene pares "clave-valor"... Así todo lo que tengo que hacer es aplicar el método keySet( ) al objeto y el resultado almacenarlo en una variable del tipo Set. Luego ¿Qué más hago? Paso el Set a un array de String y lo recorro con un ciclo for

    Creo que es mejor verlo ¿no les parece? 

    Taraaam..!!

Lista de las claves obtenida del objeto que funcionaba como valor de la clave "address".

    Genial. He obtenido una listas de keys.

    Por ultimo, probemos imprimiendo el elemento 2 del array: "suite"



    ¿Qué tal? También he logrado imprimir el elemento 2 del array.


    No hay duda de que fue emocionante para mi haber logrado mi objetivo: consumir una api y manipular el JSON para mis intereses. Fue como una "montaña rusa", momentos de pánico con una pizca de angustia y momentos de disfrute con adrenalina.

    En resumen, debo admitir que no fue fácil este camino y que aún me falta mucho por recorrer y aprender acerca de las API´s y el manejo de JSON. Pero puedo decir con toda seguridad que he "doblegado" al JSON que algún día se atrevió a desafiarme.


"No te rindas antes de que ocurra el milagro". - Fannie Flagg




Comentarios

Entradas populares