¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Cómo validar JSON con un esquema

Después de esta lección: Puedo comprobar una respuesta con un esquema.

Lección de 60 min8 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

JSON válido, datos erróneos

Validar JSON con un esquema es comparar cada campo de un registro con una lista de reglas. Las reglas dicen su tipo, si es obligatorio y qué valores se permiten. Importa porque un JSON que se analiza bien aún puede traer un número de páginas igual a «muchas».

La aplicación de una biblioteca pide a un modelo la ficha de un libro. La respuesta se analiza sin fallos. Luego un número de páginas llega como el texto «180» y la página de totales muestra disparates.

Al final de esta lección

Nota

Puedo comprobar una respuesta con un esquema.

Palabras clave

PalabraQué significaEjemplo
Esquemauna lista de comprobación de los campos de un registro
Tipola clase de valor que guarda un campointeger
Obligatorioun campo que debe estar presente
Valores permitidoslos únicos valores que un campo puede tomarnovela, historia, ciencia
Fallouna manera de romper una regla
Registroun objeto con un conjunto de campos

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un esquema es una lista de comprobación

Analizar dice que el texto es JSON. No dice que los datos sean correctos. Para eso hace falta un esquema: una regla por campo.

Una regla indica el tipo del campo, si es obligatorio y a veces sus valores permitidos. Un estándar llamado JSON Schema escribe esas reglas con un formato fijo. Aquí escribes tu propia lista de comprobación, en código.

Ejemplo resuelto: un esquema para un libro

CampoTipoObligatorioValores permitidos
titlestringsícualquier texto
pagesintegersícualquier número entero
genrestringsínovela, historia, ciencia
ratingnumbernocualquier número

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Reúne todos los fallos, no solo el primero

Una comprobación que se detiene en el primer fallo dice poco. Reúne todos los fallos en una lista, un texto corto para cada uno, como pages: tipo incorrecto.

La lista sirve para dos cosas. Decide si se acepta el registro, y la lección siguiente la devuelve al modelo como aviso.

Escribir la ayuda del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la ayuda del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' '// Un esquema es una lista de comprobación: una regla por campo.' 'const schema = [' '  { name: \"title\", type: \"string\", required: true },' '  { name: \"pages\", type: \"integer\", required: true },' '  { name: \"genre\", type: \"string\", required: true, allowed: [\"novela\", \"historia\", \"ciencia\"] },' '  { name: \"rating\", type: \"number\", required: false },' '];' > check2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function isRecord(x) {' '  if (x === null) return false;' '  if (Array.isArray(x)) return false;' '  return typeof x === \"object\";' '}' '' 'function typeOk(value, type) {' '  if (type === \"string\") return typeof value === \"string\";' '  if (type === \"integer\") return Number.isInteger(value);' '  if (type === \"number\") return typeof value === \"number\";' '  if (type === \"boolean\") return typeof value === \"boolean\";' '  return false;' '}' >> check2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Reunir todos los fallos, no solo el primero.' 'function faults(record, schema) {' '  if (isRecord(record) === false) return [\"no es un objeto\"];' '  const found = [];' '  for (const rule of schema) {' '    if (Object.prototype.hasOwnProperty.call(record, rule.name) === false) {' '      if (rule.required) found.push(rule.name + \": falta\");' '      continue;' '    }' '    const value = record[rule.name];' '    if (typeOk(value, rule.type) === false) found.push(rule.name + \": tipo incorrecto\");' '    else if (rule.allowed && rule.allowed.includes(value) === false) found.push(rule.name + \": valor no permitido\");' '  }' '  return found;' '}' >> check2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function pullJson(text) {' '  const start = text.indexOf(\"{\");' '  const end = text.lastIndexOf(\"}\");' '  if (start === -1 || end < start) return null;' '  try { return JSON.parse(text.slice(start, end + 1)); } catch (error) { return null; }' '}' '' 'const records = [' '  { title: \"Atlas de ríos\", pages: 240, genre: \"ciencia\" },' '  { title: \"Tablas de mareas\", pages: \"180\", genre: \"historia\" },' '  { title: \"Cartas de luna\", pages: 96, genre: \"poesía\", rating: 4.5 },' '  { pages: 310, genre: \"novela\", rating: \"bueno\" },' '];' 'records.forEach(function (record, at) {' '  const found = faults(record, schema);' '  console.log(\"Registro \" + (at + 1) + \":\", found.length === 0 ? \"ok\" : found.join(\", \"));' '});' >> check2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir la comprobación, parte 5

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const messages = [{ role: \"user\", content: \"Inventa un libro para una biblioteca universitaria. Responde con un objeto JSON con las claves title (texto), pages (un número entero) y genre (novela, historia o ciencia). Responde solo con el JSON.\" }];' '  // Muestra grabada, usada solo si ningún modelo responde. Rompe dos reglas a propósito.' '  const sample = JSON.stringify({ title: \"El puerto tranquilo\", pages: \"210\", genre: \"policíaca\" });' '  const reply = await ask(messages, sample, 100);' '  const record = pullJson(reply);' '  const found = faults(record, schema);' '  console.log(\"Registro del modelo:\", JSON.stringify(record));' '  console.log(\"Fallos:\", found.length === 0 ? \"ninguno\" : found.join(\", \"));' '}' 'main();' >> check2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecutar la comprobación

Comando
docker exec -w /home/node/project agent node check2.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una salida posible

LíneaLo que muestra
Registro 1ok
Registro 2pages: tipo incorrecto
Registro 3genre: valor no permitido
Registro 4title: falta, rating: tipo incorrecto
Registro del modelo y FallosCambian en cada ejecución: un registro del modelo y sus fallos, o ninguno

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un error frecuente

Advertencia

Mucha gente cree que «180» y 180 son lo mismo. Se parecen, pero un programa no puede sumar ni comparar un texto como si fuera un número. Comprueba el tipo, no el aspecto del valor.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.