Como gerar classes Java a partir de um JSON de exemplo

Cole um JSON de exemplo — uma resposta de API, um arquivo de configuração ou o corpo de um webhook — e a página escreve as classes Java correspondentes: uma classe por arquivo, com campos privados e seus métodos get e set. Defina o nome da classe raiz e o pacote, clique em Gerar JavaBean e baixe todos os arquivos em um ZIP ou copie o código direto da página. A conversão roda no navegador, o conteúdo não é enviado para nenhum servidor e a página continua funcionando offline depois de carregada.

Dois pontos da saída são intencionais. Todo nome de campo é um identificador válido em Java, e toda propriedade renomeada mantém o nome JSON original em uma anotação Jackson @JsonProperty, então a classe gerada continua mapeando o payload de origem. O restante — tipos, nomes de classe e aninhamento — é deduzido da amostra colada, por isso o resultado é um rascunho para revisão e não um modelo pronto.

  1. Cole o JSON no campo do topo. As classes são refeitas a cada tecla digitada, então dá para acompanhar o modelo mudando enquanto você edita a amostra.
  2. Ajuste Classe e Pacote se os padrões não servirem: Classe é o nome da classe raiz (RootBean) e Pacote é a linha package gravada em cada arquivo (com.example.model). Os dois são corrigidos automaticamente quando não são Java válido.
  3. Clique em Gerar JavaBean. Cada classe aparece em seu próprio bloco com o rótulo Nome da classe; o primeiro bloco é a classe raiz e os demais são as classes referenciadas por ela.
  4. Clique em Baixar código Java para receber um ZIP chamado kivtools-java-models.zip que recria as pastas do pacote e traz um arquivo .java por classe, ou em Limpar entrada para esvaziar o campo e o resultado.

Como valores, nomes e arrays viram Java

Qual tipo Java cada valor JSON recebe

Texto vira String e true ou false vira boolean. Inteiros que cabem em 32 bits viram int; inteiros maiores viram long, e inteiros fora da faixa que o JavaScript representa com exatidão viram BigDecimal para que nada seja arredondado sem aviso. Números com casa decimal viram double, e null vira String, porque um null sozinho não carrega informação de tipo.

Uma string com cara de data vira java.util.Date: 2024-05-06, 2024/05/06, 12/31/2024, May 6, 2024 e timestamps ISO 8601 com fuso horário opcional entram nessa lista. Números sem separador não entram: 20240506, 2024 e "1-2" continuam String, assim um id, um ano ou uma versão não viram data por acidente.

De nome JSON para nome Java

Um nome de propriedade que já é identificador válido é mantido como está, inclusive a caixa das letras. O resto vira camelCase pela separação nos caracteres que o Java não aceita: user_name vira userName, a.b vira aB e user name vira userName. Nomes que são palavras reservadas do Java ou começam com dígito recebem um sublinhado na frente, então {"class": 1} gera o campo _class.

Os nomes de classe seguem as mesmas regras e começam em maiúscula. Duas proteções extras entram em ação. Uma classe não pode ter o nome de um tipo que o próprio arquivo usa, por isso uma propriedade chamada list gera ListModel em vez de esconder java.util.List. E dois objetos não podem reivindicar o mesmo nome de classe — o segundo é qualificado pelo pai, então wrap.data vira WrapData enquanto o data externo continua Data. Dentro de um mesmo objeto, user_name e userName colidem e o segundo campo vira userName2. A anotação vem de com.fasterxml.jackson.annotation.JsonProperty, o pacote do Jackson 2.

Objetos, arrays e modelos aninhados

Um objeto aninhado vira uma classe própria, com o nome da propriedade que o guarda, e o campo aponta para essa classe. Arrays viram List<...>: um array de strings é List<String>, um array de objetos é List<Users> mais a classe Users, e um array aninhado mantém a profundidade, então [[1,2]] é List<List<Integer>>. Argumentos de tipo são sempre com wrapper — List<Integer> e nunca List<int> — porque o Java não aceita primitivos ali.

Em um array de objetos todos os elementos são lidos, não só o primeiro: um campo que aparece em alguns elementos também é incluído, arrays dentro desses objetos são combinados e uma propriedade com tipos diferentes em elementos diferentes vira Object. Um array vazio não traz tipo de elemento, então o elemento é tipado como String como marcador. Um array no nível superior recebe o mesmo tratamento: a classe raiz é montada com as propriedades de todos os elementos.

O que os arquivos gerados são — e o que não são

Cada arquivo traz a linha package, os imports que ele realmente usa, um cabeçalho Javadoc curto com o horário de geração e o endereço desta página, uma classe pública e campos privados com get e set. Não há Lombok, builder, equals nem hashCode: a saída é um JavaBean simples que precisa apenas do JDK e, quando algum campo foi renomeado, das anotações Jackson no classpath.

Nada é compilado nem verificado contra o seu projeto aqui, e os tipos vêm de uma única amostra. Campos opcionais, nulls aninhados ou um valor que troca de tipo entre chamadas não aparecem nessa amostra, e um número que hoje é int vira um campo primitivo que talvez você precise envolver depois. Algumas centenas de kilobytes são convertidas no navegador em bem menos de um segundo, então uma resposta grande não é problema — mas a amostra é uma foto, não um esquema.

Ferramentas recentes: