Ir para o conteúdo
AZ Tools

Validador de JSON Schema

Cole um esquema à esquerda e um documento à direita para saber se o documento valida e, quando não valida, exatamente onde e por quê. Cada erro é uma linha: o JSON Pointer dentro do documento, a palavra-chave que falhou, o ponto do esquema de onde ela veio, o valor que estava lá e — o que um ponteiro sozinho nunca dá — a linha do texto colado em que o ponteiro cai. As linhas seguem a ordem em que você leria o arquivo, então a primeira é o primeiro problema que encontraria rolando a tela. O que faz esta ferramenta valer é o relatório de anyOf e oneOf. A maioria dos validadores achata isso: um valor que erra em três ramos produz todas as reclamações dos três numa lista indiferenciada, e a frase útil fica soterrada. Aqui a falha continua sendo uma linha, com os ramos abaixo dela, cada um descrito pelo que exige e com os próprios erros, e o que chegou mais perto — o de menos problemas — marcado, porque quase sempre é o ramo que você queria. Um oneOf que casa com dois ramos é relatado como falha própria e nomeia os ramos. O draft importa mais do que parece, então a ferramenta mostra qual usou e como escolheu: o $schema do esquema, quando existe, senão o que você selecionar. No draft 4, 1.0 não é inteiro e exclusiveMinimum é um booleano que modifica minimum; do draft 6 em diante, 1.0 é inteiro e exclusiveMinimum carrega o limite. No draft 7 e anteriores, qualquer palavra-chave escrita ao lado de um $ref é ignorada. Outras respostas surpreendem igual em todos os drafts: required fala de presença, então uma propriedade em null o satisfaz; minLength conta pontos de código, então um emoji é um e um acento decomposto são dois; 0.3 não é múltiplo de 0.1 em ponto flutuante binário; e dois objetos que só diferem na ordem das chaves são o mesmo valor, enquanto dois arrays em ordens diferentes não são. Um esquema também pode estar quebrado em vez de rigoroso, e essa é outra resposta. Um nome de tipo escrito errado, um required que não é array, um pattern que não compila ou um $ref que não resolve são relatados como falha do esquema, com um ponteiro para o lugar, em vez de virarem um documento que passa ou reprova. O que ela não pode dizer: nada é baixado da rede, então um $ref para uma URL não resolve aqui e precisa ser trazido para $defs; unevaluatedProperties, unevaluatedItems e $dynamicRef são sinalizados e pulados em vez de adivinhados; inteiros acima de 2^53 são lidos como doubles, o que um validador de servidor não faz; e os padrões rodam no motor de expressões regulares do navegador, que é o que a especificação pede mas difere de Python ou Go nas bordas. Tudo acontece na página: nem o esquema nem o documento saem da sua máquina.

format é apenas uma anotação por padrão. Ligue isto para que ele falhe de verdade.

Se o esquema declara $schema, esse draft vale; esta opção só é usada quando ele não declara.

Resultado

Inválido

Erros

7

Draft

2020-12

Documento

12 linhas, 169 bytes

7 erros2020-12 · escolhido pelo $schema
o documento inteirolinha 1additionalProperties

O esquema não permite outras propriedades e estas estão aqui: "debug"

debug (linha 11)

valor: {"name":"","version":"2.1","server":{"host":"0.0.0.0","port":99999,"tls":"yes"},"workers":…

esquema: /additionalProperties

/namelinha 2minLength

A string tem 0 pontos de código e o mínimo é 1

valor: ""

esquema: /properties/name/minLength

/versionlinha 3pattern

"2.1" não corresponde ao padrão ^\d+\.\d+\.\d+$

valor: "2.1"

esquema: /properties/version/pattern

/server/portlinha 6maximum

99999 é maior que o máximo de 65535

valor: 99999

esquema: /properties/server/properties/port/maximum

/server/tlslinha 7type

"yes" é do tipo string e o esquema pede boolean

valor: "yes"

esquema: /properties/server/properties/tls/type

/workerslinha 9anyOf

Nenhum dos 2 ramos de anyOf aceita este valor

valor: 0

esquema: /properties/workers/anyOf

Ramo a ramo

Ramo 1 type: integer 1 problemaso mais próximo

  • /workers — 0 é menor que o mínimo de 1

Ramo 2 const: "auto" 1 problemas

  • /workers — 0 não é a constante "auto"
/tagslinha 10uniqueItems

Os itens de índice 0 e índice 1 são o mesmo valor: "a"

valor: ["a","a"]

esquema: /properties/tags/uniqueItems

Tudo roda nesta página: nem o esquema nem o documento são enviados.

Como usar

  1. Cole o esquema na primeira caixa e o documento que quer verificar na segunda. As duas guardam o que você digitou, então dá para fechar a página e voltar.
  2. Olhe os cartões de resumo: válido ou não, quantos erros, qual draft foi usado e o tamanho do documento. A linha do draft diz ainda se ele veio do $schema ou do seletor.
  3. Percorra as linhas de erro. Cada uma dá o JSON Pointer, a linha do seu documento, a palavra-chave que falhou, o valor que estava lá e o lugar dentro do esquema, para você decidir qual lado corrigir.
  4. Abra uma linha de anyOf ou oneOf e leia os ramos. O marcado como mais próximo é o que falhou em menos coisas, que normalmente é o que você tinha em mente.
  5. Ligue "Verificar format" quando quiser que format falhe em vez de apenas anotar: vem desligado porque a especificação o define como anotação e a maioria dos validadores deixa assim.

Perguntas frequentes

Por que meu documento passa quando eu esperava que falhasse?
Quase sempre porque o esquema diz menos do que parece dizer. JSON Schema ignora palavras-chave que não conhece, então "require" em vez de "required", "minlength" em vez de "minLength" ou uma palavra de 2020-12 dentro de um esquema draft-07 não é erro: é uma anotação que não faz nada. Objetos também aceitam propriedades extras a menos que additionalProperties ou unevaluatedProperties diga o contrário, arrays aceitam qualquer coisa sem items ou prefixItems, e format apenas anota até você ligar a verificação. Confira também o draft nos cartões: uma palavra-chave pode existir em um draft e não em outro, e aqui é ignorada a que o draft escolhido nunca teve.
1.0 é um inteiro?
Do draft 6 em diante, sim: a especificação define "integer" pelo valor, então 1.0 e 1.0e2 são inteiros e 1.5 não é. No draft 4, não: um número escrito com parte decimal é float e falha em "type": "integer". Esta ferramenta guarda como cada número foi escrito durante a análise, e é só por isso que consegue distinguir 1 de 1.0 — o JSON.parse entrega o mesmo valor para os dois. Se você valida com uma biblioteca antiga contra um esquema draft-04, essa diferença é fonte real de surpresas em produção, e trocar o seletor de draft aqui a reproduz.
Por que 0.3 não é múltiplo de 0.1?
Porque nenhum dos dois números é exato em ponto flutuante binário. 0.3 dividido por 0.1 dá 2.9999999999999996, não 3, e os validadores de referência testam exatamente esse quociente, então o documento é rejeitado. O mesmo esquema escrito como "multipleOf": 1 com o valor escalado para 3 passa. Não é mania desta ferramenta: python-jsonschema, ajv e os outros se comportam assim com multipleOf decimal, e por isso um esquema que quer dizer "duas casas decimais" fica melhor como pattern ou como um inteiro de centavos.
Como se lê o JSON Pointer de um erro?
Um ponteiro é um caminho de tokens separados por barras a partir da raiz do documento: /server/port é o membro port do objeto server e /tags/2 é o terceiro elemento de tags, porque os índices começam em zero. Um ponteiro vazio significa o documento inteiro, e é por isso que erros de required, additionalProperties e uniqueItems apontam para o objeto ou o array que os contém, e não para o membro: a propriedade ausente não tem lugar próprio. Uma barra dentro de um nome de propriedade se escreve ~1 e um til se escreve ~0. O número de linha ao lado do ponteiro é esta ferramenta resolvendo esse caminho no texto exato que você colou.
Por que outros validadores despejam tantos erros no anyOf?
Porque um anyOf que falhou realmente falhou em todos os ramos, e todos aqueles erros são verdadeiros. Um validador sem critério imprime todos lado a lado, então uma união de string e objeto vira uma lista em que "não é do tipo string" aparece junto de uma reclamação por propriedade ausente de um objeto que você nunca quis. Agrupar por ramo devolve a estrutura que o esquema já tinha, e escolher o ramo com menos falhas leva ao pretendido quase sempre. É heurística, não prova: quando dois ramos falham em uma coisa cada, a ferramenta marca o primeiro, e o esquema sozinho não diz qual você queria.
Ela segue um $ref para outro arquivo ou para uma URL?
Não, e isso é proposital: nada aqui toca a rede, então um $ref para https://example.com/user.json, ou para um arquivo vizinho como common.json#/$defs/id, não pode ser resolvido e é relatado como falha do esquema em vez de ser ignorado em silêncio. As referências dentro do texto colado funcionam por inteiro: #/$defs/name, um # sozinho, uma referência recursiva à raiz, um $anchor e um $id que outra referência nomeie. Para verificar um esquema espalhado em arquivos, junte tudo antes: cole as definições em $defs e reaponte as referências, que é o que a maioria das ferramentas faz antes de publicar um esquema.

Ferramentas relacionadas