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.

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)