Como gerar classes C# a partir de uma amostra JSON

Cole uma amostra JSON — uma resposta de API, um arquivo de configuração ou o corpo de um webhook — e esta página escreve as classes C# correspondentes: uma classe por formato de objeto, com propriedades públicas e acessores { get; set; }, tudo em um único arquivo que você pode copiar. A conversão roda no seu navegador, o payload nunca é enviado e a página continua funcionando offline depois de carregada.

Todo nome de propriedade é um identificador legal de C#: uma chave que colide com palavra reservada vira um identificador literal (@class) e uma chave com caracteres que o C# não aceita é reconstruída mantendo a chave original em um atributo [JsonPropertyName], para que o System.Text.Json continue mapeando o payload. Os tipos, os nomes de classe e o aninhamento saem da amostra que você colou, por isso o resultado é um rascunho para revisar, não um modelo pronto.

  1. Cole ou digite o JSON no campo acima. Comentários são aceitos: uma linha // ou /* */ sozinha acima de uma propriedade vira uma linha /// <summary> na classe gerada.
  2. Pressione Gerar classes C#. O arquivo aparece abaixo, colorido com a gramática de C#, e a mensagem acima confirma a execução ou indica a linha que a interrompeu.
  3. Pressione Copiar classes C# para levar o código sem cores para a área de transferência e cole em um arquivo .cs do seu projeto.
  4. Edite o JSON e gere de novo quando algum valor não fizer sentido: o resultado anterior é apagado em toda execução, inclusive nas que falham, então o que você copia sempre pertence à entrada atual.

Como valores, chaves e arrays viram C#

Qual tipo C# cada valor JSON recebe

Os números são tipados por faixa: um inteiro que cabe em Int32 vira int, um inteiro maior vira long até 2^53, e o que tiver casas decimais ou passar desse limite vira double, então 2147483648 e 1e10 não caem mais em um int. true e false viram bool, e um valor que é null em toda a amostra vira string. Uma string continua string a menos que tenha formato de data e possa ser interpretada como uma: 2024-05-06, 2024/05/06 10:00, 12/31/2024 e May 6, 2024 viram DateTime, enquanto 20240506, 1-2, R2D2 e identificadores numéricos mantêm o texto exato.

Quando um mesmo campo carrega tipos diferentes entre os elementos de um array, o tipo numérico mais amplo vence (int com long dá long, int com 2.5 dá double) e qualquer outra divergência vira object. Um campo que é null em um elemento e tipado em outro assume o tipo do elemento não nulo, então um null não apaga o que as outras linhas mostram.

Como uma chave JSON vira uma propriedade C#

A propriedade mantém a chave JSON sempre que o C# permite. Uma chave que é palavra reservada vira identificador literal, então class vira @class, que compila e continua mapeando a chave de mesmo nome. Uma chave com caracteres que o C# rejeita é reconstruída: user-name vira userName, first name vira firstName, 1st vira _1st, a.b vira aB e uma chave vazia vira value. Duas chaves que chegam ao mesmo identificador recebem um sufixo numérico em vez de se sobrescreverem, então a.b e a&b ficam como aB e aB2.

Sempre que o nome da propriedade difere da chave JSON, a propriedade leva [JsonPropertyName("...")] e o arquivo ganha um using System.Text.Json.Serialization; o atributo é omitido quando apenas repetiria o nome da propriedade, e uma chave reservada como class não precisa dele porque o nome literal já coincide. Esse atributo é a única configuração escrita no arquivo: sem opções de serializador, sem schema e sem anotação para as chaves que não mudaram.

Objetos, arrays e classes aninhadas

Cada formato de objeto distinto vira uma classe, nomeada a partir da chave JSON em PascalCase e nunca repetida no arquivo: um segundo data vira Data2 e um data aninhado dentro de wrap vira WrapData, então dois ramos não podem mais reivindicar Data. Uma classe também nunca recebe o nome dos tipos que o próprio arquivo usa (List, String, Object, DateTime), porque isso os sombrearia, e um membro nunca pode repetir o nome da própria classe.

Os arrays são lidos por inteiro, não só pelo primeiro elemento: [1, 2, 3] vira List<int>, [1, 2.5] vira List<double>, um array de objetos vira uma lista de uma classe mesclada com todas as chaves que aparecem em qualquer elemento, e um array que mistura objetos e escalares vira List<object>. Um array vazio vira List<string> como marcador. O objeto raiz chama-se sempre Root; um array na raiz é anotado em um comentário e modelado a partir dos elementos mesclados, e uma raiz escalar gera uma classe vazia com um comentário dizendo que nenhuma propriedade pôde ser inferida.

O que o arquivo gerado é, e o que ele não é

A saída é um único arquivo de código C#: um comentário de geração com o horário, as diretivas using que o arquivo realmente precisa e, depois, as classes. É C# puro, com propriedades { get; set; }, sem construtor e sem namespace, então entra em qualquer projeto a partir do .NET Core 3.0; nada aqui compila o código, a página apenas escreve o texto.

Os tipos vêm da única amostra que você cola, então um campo que é sempre 0 na amostra fica int mesmo que a produção envie um decimal, e um array que por acaso está vazio fica List<string>. Trate o resultado como rascunho: confira os tipos em que você confia, renomeie a classe raiz como quiser e mantenha os comentários JSON da amostra, porque são a única parte da entrada que vira documentação.

Ferramentas recentes: