Utilidades JSON para NVDA.

Modo de uso

  • NVDA+j: si hay texto seleccionado, toma el texto JSON seleccionado y lo muestra formateado en un diálogo explorable de NVDA. Si no hay texto seleccionado, muestra el diálogo con texto JSON formateado que toma del portapapeles.
  • NVDA+shift+j: formatea varios JSON de un mismo texto

Cómo funciona la característica multi JSON

Hay situaciones en las que tenemos varios JSON, uno por línea (líneas de registro, por ejemplo):

{"datetime": "2022-03-10 21:04:05", "level": "info", "message": "user logged in"}
{"datetime": "2022-03-10 21:04:08", "level": "error", "message": "Database is down"}


Al pulsar «NVDA+shift+j», este complemento toma cada línea, formatea y muestra todos los elementos como una lista.
El texto formateado se mostrará de la siguiente manera:

[
    {
        "datetime": "2022-03-10 21:04:05",
        "level": "info",
        "message": "user logged in"
    },
    {
        "datetime": "2022-03-10 21:04:08",
        "level": "error",
        "message": "Database is down"
    }
]

Filtrado/transformación de JSON

Este complemento te permite filtrar o transformar JSON usando JQ o JSONPath. De forma predeterminada, se usa JQ, pero puedes cambiarlo en el panel de opciones de NVDA.
Al abrir el cuadro de diálogo JSON con «NVDA+j» o «NVDA+shift+j», se pueden ver tres cuadros de texto: texto original, expresión de consulta y salida. Se debe usar el segundo campo de texto para filtrar/transformar JSON. Escribe la consulta, pulsa intro y comprueba el resultado en el campo de texto de «salida».
Para probar esta función se puede utilizar este archivo de registro falso:

{"timestamp": "2024-11-07T14:12:45Z", "level": "INFO", "trace_id": "abc123", "span_id": "span789", "message": "User login successful"}
{"timestamp": "2024-11-07T14:13:12Z", "level": "ERROR", "trace_id": "def456", "span_id": "span101", "message": "Failed to connect to database"}
{"timestamp": "2024-11-07T14:15:30Z", "level": "DEBUG", "trace_id": "ghi789", "span_id": "span202", "message": "Fetching data from cache"}
{"timestamp": "2024-11-07T14:17:02Z", "level": "WARN", "trace_id": "jkl012", "span_id": "span303", "message": "High memory usage detected"}
{"timestamp": "2024-11-07T14:19:25Z", "level": "INFO", "trace_id": "mno345", "span_id": "span404", "message": "Background job started"}
{"timestamp": "2024-11-07T14:21:58Z", "level": "ERROR", "trace_id": "pqr678", "span_id": "span505", "message": "Timeout while waiting for external API response"}
{"timestamp": "2024-11-07T14:23:47Z", "level": "DEBUG", "trace_id": "stu901", "span_id": "span606", "message": "User profile data parsed successfully"}
{"timestamp": "2024-11-07T14:25:15Z", "level": "WARN", "trace_id": "vwx234", "span_id": "span707", "message": "Deprecated API version called"}
{"timestamp": "2024-11-07T14:27:33Z", "level": "INFO", "trace_id": "yzb567", "span_id": "span808", "message": "File uploaded successfully"}
{"timestamp": "2024-11-07T14:29:09Z", "level": "ERROR", "trace_id": "cde890", "span_id": "span909", "message": "Null pointer exception encountered"}

JQ

JQ es como un lenguaje de programación para filtrar y transformar datos JSON. Debido a esta flexibilidad, este es el motor de consulta predeterminado que se utiliza en este complemento.
Ejemplos de programas JQ:

Consultas JQ acompañadas de sus descripciones
Consulta Descripción
Obtener JSON original .
Extraer todos los mensajes de registro .[].message
Obtener todos los registros INFO .[] | select(.level == «INFO»)
Obtener un objeto sólo con marcas de tiempo y mensajes de tipo WARN .[] | select(.level == «WARN») | {timestamp, message}
Obtener la marca de tiempo de los registros que contienen «cache» en el mensaje .[] | select(.message | test(«cache»)) | .timestamp
Obtener solo los campos «mensaje» y «marca de tiempo», agrupados por nivel group_by(.level) | map({(.[0].level): map({message: .message, timestamp: .timestamp})})
Obtener los tres primeros registros con nivel debug .[] | select(.level == «DEBUG») | . | limit(3;.)
Agregar un campo «is_critical=true» a los niveles de ERROR y falso a los demás .[] | .is_critical = (.level == «ERROR») | .
Eliminar registros DEBUG map(select(.level != «DEBUG»))
Ordenar registros por marca de tiempo, ascendente sort_by(.timestamp)
JSONPath

JSONPath es una sintaxis que permite filtrar elementos JSON. Puedes conocerla mejor consultando su documentación.
Consultas de ejemplo:

Consultas de ejemplo de JSONPath
Descripción Consulta
Obtener JSON original $
Extraer todos los mensajes de registro $..message
Obtener registros con nivel = ERROR $[?(@.level == ‘ERROR’)]
Extraer el campo «trace_id» de todos los registros INFO $[?(@.level == ‘INFO’)].trace_id
Obtener todos los registros que no son de depuración $[?(@.level != ‘DEBUG’)]
Extraer todos los registros antes de una marca de tiempo $[?(@.timestamp > ‘2024-11-07T14:20:00Z’)]

Transformación de cadenas con JSONPointer (NVDA+ctrl+j)

Dado este JSON:

{
    "name": "Josiel",
    "family": {
        "mother": {"name": "Maria"}
    },
    "programming_languages": ["Java", "PHP"]
}


Con esta funcionalidad se pueden crear cadenas usando marcadores de posición con sintaxis JSONPointer:
Mi nombre es {/name}, mi madre es {/family/mother/name} y mi lenguaje de programación favorito es {/programming_languages/1}
Resultado:
Mi nombre es Josiel, mi madre es Maria y mi lenguaje de programación favorito es PHP

Uso de autocompletar

En el campo de edición de expresión:

  • Pulsa control+intro para ejecutar y guardar una consulta.
  • Escribe parte de la expresión.
  • Utiliza las flechas arriba y abajo para moverte por la lista de sugerencias.

En la lista de sugerencias:

  • Pulsa intro para rellenar el campo con la expresión elegida y ejecutarla.
  • Pulsa retroceso para borrar el último carácter y situar el foco en el cuadro de edición.
  • Pulsa suprimir para borrar la expresión guardada.

Características (implementadas y futuras)

  • Analizar JSON desde el portapapeles
  • Analizar JSON a partir del texto seleccionado (cursor)
  • Análisis de múltiples cadenas JSON (una por línea)
  • Panel de configuración
    • Opción para seleccionar el motor de consulta a utilizar
    • Configurar el comportamiento de los scripts (tomar JSON solo del texto seleccionado, solo del portapapeles o ambos (actual))
  • Análisis de variantes de JSON
    • JSON original que utiliza el módulo json de Python
    • json5
  • JSON interactivo a través de una interfaz de usuario
    • Botón para copiar la salida al portapapeles
    • Filtrado/transformación de JSON
      • Con JSONPath ( https://goessner.net/articles/JsonPath/ , https://github.com/h2non/jsonpath-ng )
      • Con JQ ( https://jqlang.github.io/jq/ , https://github.com/mwilliamson/jq.py )
      • Guardar filtros/transformaciones para evitar escribir (programa y descripción)
      • Autocompletar con consultas guardadas
      • Transformación de cadenas mediante JSONPointer ( https://datatracker.ietf.org/doc/html/rfc6901 , https://github.com/stefankoegl/python-json-pointer?tab=readme-ov-file )

Autor: José Manuel Delicado Alcolea

Ingeniero de software y máster en Ingeniería Informática por la Universidad Rey Juan Carlos. Me encanta todo lo relacionado con la informática, la accesibilidad y las nuevas tecnologías. Trabajo como consultor de accesibilidad.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.