Cuando recién comencé a explorar los JSON’s me tope con el mismo problema que cuando empecé a analizar los archivos XML: No tenía ni idea de que archivo contenía qué información. Sin duda, esto me hacía sentir como un solitario e insignificante punto en un caduco planeta orbitado por un Sol frío e indiferente.
Así que para dejar de sentirme como un solitario e insignificante punto en un caduco planeta orbitado por un Sol frío e indiferente, me dí a la tarea de resolver el problema del “que contiene que” en Gameday. Decidí empezar por el archivo contextMetrics, ya que a simple vista es el que parece tener una estructura más sencilla.
De antemano sabía que la estructura de un JSON es como la de un árbol genealógico: Comienza con una rama principal que tiene ramificaciones y a su vez, cada ramificación puede tener más ramificaciones. Así que pronto entendí que me enfrentaba a un problema cuya solución debía estar dada por un código recursivo.
Un problema que se soluciona por medio de un código recursivo, es básicamente un problema donde el código se ejecuta así mismo n veces, siendo n es el número de sub-problemas que componen al problema principal.
De este modo, si quisiéramos conocer el número total de ramas que componen a la rama principal del árbol de la imagen, primero tendríamos que contar las ramas que se desprenden directamente de esta. Posteriormente, tendríamos que contar las ramificaciones que se desprenden de cada una de las ramas que nacen de la rama principal y así sucesivamente hasta recorrer todo el árbol.
Basado en lo anterior, escribí el siguiente código que tiene dos funciones recursivas. La primera, recorre el JSON para un juego de Gameday y crea un diccionario a partir de la estructura de este. La segunda, simplemente imprime tal diccionario.
import requests
def obtenerEstructura( diccionario, estructura ):
for llave in diccionario:
if isinstance( diccionario[llave], dict ):
estructura[llave] = obtenerEstructura( diccionario[llave], {} )
else:
estructura[llave] = type( diccionario[llave] ).__name__
return estructura
def imprimirEstructura( estructura, numEspacios ):
espacios = ' '*( 4*numEspacios )
for llave in estructura:
if isinstance( estructura[llave], dict ):
print( espacios+llave+':')
print( espacios+'{' )
imprimirEstructura( estructura[llave], numEspacios + 1 )
print( espacios+'}' )
else:
print( espacios+llave+' : '+estructura[llave] )
miTexto = requests.get('http://statsapi.mlb.com/api/v1/game/431674/contextMetrics')
miJson = miTexto.json()
estructura = obtenerEstructura( miJson, {} )
print( '{' )
imprimirEstructura( estructura, 1 )
print( '}' )
Puedes encontrar el resultado de la segunda función aqui. No lo agregue dentro del post porque el resultado es un poco largo :).
Por último, solo me resta decir que algunos archivos de Gameday tienen estructuras un tanto complejas entre las que podemos encontrar listas de diccionarios y viceversa. También debo mencionar que los datos de un archivo pueden variar de un partido a otro, por lo que encontrar la estructura correcta de un archivo de Gameday puede requerir el análisis de múltiples juegos.
Espero que este post te haya servido para entender lo que es la recursividad y cómo la implementamos para solucionar un problema relacionado con Béisbol.