Como verificar se uma determinada string é JSON válida em Java

155

Como validar uma string JSON em Java? Ou eu poderia analisá-lo usando expressões regulares?

sappu
fonte
tente analisar com gson? validando através de regex pode não ser uma boa idéia
aishwarya
2
json.org tem links para muitos analisadores
Martink

Respostas:

261

Uma ideia selvagem, tente analisá-la e pegue a exceção:

import org.json.*;

public boolean isJSONValid(String test) {
    try {
        new JSONObject(test);
    } catch (JSONException ex) {
        // edited, to include @Arthur's comment
        // e.g. in case JSONArray is valid as well...
        try {
            new JSONArray(test);
        } catch (JSONException ex1) {
            return false;
        }
    }
    return true;
}

Esse código usa a implementação da API JSON org.json, disponível no github , no maven e parcialmente no Android .

MByD
fonte
2
É perto, mas está faltando uma validação para um JSONArray (i tenho atualizado este post com uma função mais adequada)
Arthur
9
Eu tentei uma string json como "{'hello': 'foo'} 'invalid'" (adicionada 'invalid' fora do {}), e JSONObject não está lançando ParseException. Estou usando org.json.JSONObject. Isso é esperado?
Soichi Hayashi
16
Você não mencionou a biblioteca que possui JSONObject, eu não a vi na java lib padrão
Krzysztof Krasoń
6
Esta solução funciona na maioria dos casos, mas pode falhar em determinadas circunstâncias. Por exemplo, ele permite a vírgula logo antes da chave de fechamento, que na verdade é um erro de sintaxe. Consulte json.org/javadoc/org/json/JSONObject.html para outros casos de canto.
Hua2308
9
Não consigo entender por que os pôsteres não podem se incomodar em incluir instruções de importação com trechos de código. É importante aqui. A segunda resposta classificada aqui é muito melhor.
seansand
100

Biblioteca JACKSON

Uma opção seria usar a biblioteca Jackson . Primeiro importe a versão mais recente (agora é):

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.0</version>
</dependency>

Em seguida, você pode implementar a resposta correta da seguinte maneira:

import com.fasterxml.jackson.databind.ObjectMapper;

public final class JSONUtils {
  private JSONUtils(){}

  public static boolean isJSONValid(String jsonInString ) {
    try {
       final ObjectMapper mapper = new ObjectMapper();
       mapper.readTree(jsonInString);
       return true;
    } catch (IOException e) {
       return false;
    }
  }
}

Opção Google GSON

Outra opção é usar o Google Gson . Importe a dependência:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.5</version>
</dependency>

Novamente, você pode implementar a solução proposta como:

import com.google.gson.Gson;

public final class JSONUtils {
  private static final Gson gson = new Gson();

  private JSONUtils(){}

  public static boolean isJSONValid(String jsonInString) {
      try {
          gson.fromJson(jsonInString, Object.class);
          return true;
      } catch(com.google.gson.JsonSyntaxException ex) { 
          return false;
      }
  }
}

Um teste simples segue aqui:

//A valid JSON String to parse.
String validJsonString = "{ \"developers\": [{ \"firstName\":\"Linus\" , \"lastName\":\"Torvalds\" }, " +
        "{ \"firstName\":\"John\" , \"lastName\":\"von Neumann\" } ]}";

// Invalid String with a missing parenthesis at the beginning.
String invalidJsonString = "\"developers\": [ \"firstName\":\"Linus\" , \"lastName\":\"Torvalds\" }, " +
        "{ \"firstName\":\"John\" , \"lastName\":\"von Neumann\" } ]}";

boolean firstStringValid = JSONUtils.isJSONValid(validJsonString); //true
boolean secondStringValid = JSONUtils.isJSONValid(invalidJsonString); //false

Observe que pode haver um problema "menor" devido às vírgulas à direita que serão corrigidas na versão 3.0.0.

Jean Valjean
fonte
Enquanto isso funciona para grandes coisas como citações incompatíveis, ou parênteses desaparecidas, Gson terá todo o prazer analisar uma matriz JSON com uma vírgula à direita, que não está de acordo com RFC-4627
Eurythmia
@eurythmia True! Na versão 3.0 devem corrigir o problema
Jean Valjean
1
Isso valida {chave: valor} também, mas não é um JSON válido
Pratapi Hemant Patel
2
new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")Armadilha de JACKSON: analisa sem exceção como IntNode (28). Realmente não é esperado ... #
11168
1
Pelo que entendi, esta solução não apenas valida, mas analisa (e armazena) todo o json. Ele converte números em Inteiro / Longo / Duplo, etc. Isso é mais do que apenas verificação de sintaxe, ele armazena json inteiro na memória. Isso pode ser significativo para cargas intensivas. Se existe uma solução melhor para a verificação de sintaxe?
javapowered
15

Com o Google Gson, você pode usar o JsonParser:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Cristian
fonte
3
Observe que isso não gera um erro em seqüências de caracteres sem bracketing ala "asdf"
Andrew
1
Também não rejeita vírgulas finais em matrizes JSON.
Sotirios Delimanolis
Eu realmente não posso confiar nisso ... diz que a string "Salvar" é analisável.
Dherik
Cuidado que o exemplo do gson aqui usa o modo de análise branda que ainda permite muitos desvios. Veja mais detalhes com testcase e exemplo de análise rigorosa em minhas outras respostas.
Vadzim
14

Você poderia usar o .mayBeJSON (String str) disponível na biblioteca JSONUtils .

npinti
fonte
sim ... isso está funcionando. Obrigado npinti. Eu estava tentando com o Gson, mas não existe esse método que eu já vi.
sappu
@appu: Se esta resposta resolveu sua pergunta, marque-a assim. A maioria das bibliotecas tende a absorver uma String e tenta analisá-la, se a análise falhar, ou seja, a string não é uma string JSON válida, lançará uma exceção.
Npinti 16/04
@ npinti: falha no extra}. Retorna true para string inválida com colchete extra =>}
Vivek
3
Esse método literalmente apenas verifica se a sequência começa e termina com aspas ou colchetes. Muito pouco confiável.
Michael Munsey
2
é por isso que o nome do método é 'talvez', não 'é' :)
Khoa
5

Depende do que você está tentando provar com sua validação. Certamente analisar o json como outros sugeriram é melhor do que usar regexes, porque a gramática do json é mais complicada do que pode ser representada apenas com regexes.

Se o json for analisado apenas pelo seu código java, use o mesmo analisador para validá-lo.

Mas apenas analisar não necessariamente indica se será aceito em outros ambientes. por exemplo

  • muitos analisadores ignoram vírgulas finais em um objeto ou matriz, mas as versões antigas do IE podem falhar quando atingem uma vírgula final.
  • Outros analisadores podem aceitar uma vírgula à direita, mas adicionar uma entrada indefinida / nula depois dela.
  • Alguns analisadores podem permitir nomes de propriedades sem aspas.
  • Alguns analisadores podem reagir de maneira diferente a caracteres não ASCII em seqüências de caracteres.

Se sua validação precisar ser muito completa, você poderá:

Nicholas Daley
fonte
4
String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");

Faça o download da biblioteca stringtree-json

Jamsheer
fonte
É possível definir uma String como acima? Ou é apenas para a Idea.
Santron Manibharathi
não é possível, que foi devido a meus mistake.now seus corrected.Thanks
Jamsheer
1
JSONValidatingReader não faz parte da API Java
IgorGanapolsky
Por favor, use a biblioteca acima mencionada, Obrigado
Jamsheer 4/17/17
2

Um pouco sobre a análise:

O Json e, de fato, todos os idiomas, usam uma gramática, que é um conjunto de regras que podem ser usadas como substituições. para analisar json, você precisa basicamente trabalhar essas substituições em sentido inverso

Json é uma gramática livre de contexto , o que significa que você pode ter objetos / matrizes infinitamente aninhados e o json ainda seria válido. regex apenas lida com gramáticas regulares (daí o 'reg' no nome), que é um subconjunto de gramáticas livres de contexto que não permite aninhamento infinito, por isso é impossível usar apenas regex para analisar todo json válido. você pode usar um conjunto complicado de regex e loops com a suposição de que ninguém irá aninhar, digamos, 100 níveis de profundidade, mas ainda assim seria muito difícil.

se você está disposto a escrever seu próprio analisador,
você pode fazer um analisador de descida recursivo depois de elaborar a gramática

Austin_Anderson
fonte
2

Verifique se uma determinada sequência é JSON válida no Kotlin . I Resposta convertida de MByD Java para Kotlin

fun isJSONValid(test: String): Boolean {
    try {
        JSONObject(test);
    } catch (ex: JSONException) {
        try {
            JSONArray(test);
        } catch (ex1: JSONException) {
            return false;
        }
    }
    return true;
}
Bhavesh Hirpara
fonte
1

Aqui, você pode encontrar uma ferramenta que pode validar um arquivo JSON ou apenas desserializar seu arquivo JSON com qualquer biblioteca JSON e, se a operação for bem-sucedida, ela deverá ser válida ( google-json, por exemplo, que lançará uma exceção se a entrada está analisando não é JSON válido).

talnicolas
fonte
1

Usando o Playframework 2.6, a biblioteca Json encontrada na java api também pode ser usada para simplesmente analisar a string. A cadeia pode ser um elemento json da matriz json. Como o valor retornado não é importante aqui, apenas capturamos o erro de análise para determinar se a sequência é uma sequência json correta ou não.

    import play.libs.Json;

    public static Boolean isValidJson(String value) {
        try{
            Json.parse(value);
            return true;
        } catch(final Exception e){
            return false;
        }
    }
Baah
fonte
1

IMHO, a maneira mais elegante é usar a API Java para JSON Processing (JSON-P), um dos padrões JavaEE em conformidade com o JSR 374 .

try(StringReader sr = new StringReader(jsonStrn)) {
    Json.createReader(sr).readObject();
} catch(JsonParsingException e) {
    System.out.println("The given string is not a valid json");
    e.printStackTrace();
}

Usando o Maven, adicione a dependência no JSON-P:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1.4</version>
</dependency>

Visite a página oficial do JSON-P para mais informações.

Domenico
fonte
1

Aqui está um exemplo de trabalho para análise estrita do json com a biblioteca gson :

public static JsonElement parseStrict(String json) {
    // throws on almost any non-valid json
    return new Gson().getAdapter(JsonElement.class).fromJson(json); 
}

Consulte também minha outra resposta detalhada em Como verificar se o JSON é válido em Java usando o GSON com mais informações e caso de teste estendido com vários exemplos não válidos.

Vadzim
fonte
1

Como você pode ver, existem muitas soluções, elas analisam principalmente o JSON para verificá-lo e, no final, você precisará analisá-lo para ter certeza.

Mas, dependendo do contexto, você pode melhorar as performances com uma pré-verificação.

O que faço quando chamo APIs, é apenas verificar se o primeiro caractere é '{' e o último é '}'. Se não for o caso, não me incomodo em criar um analisador.

Orden
fonte
0

Eu encontrei uma solução muito simples para isso.

Por favor, primeiro instale esta biblioteca net.sf.json-libpara ela.

    import net.sf.json.JSONException;

    import net.sf.json.JSONSerializer;

    private static boolean isValidJson(String jsonStr) {
        boolean isValid = false;
        try {
            JSONSerializer.toJSON(jsonStr);
            isValid = true;
        } catch (JSONException je) {
            isValid = false;
        }
        return isValid;
    }

    public static void testJson() {
        String vjson = "{\"employees\": [{ \"firstName\":\"John\" , \"lastName\":\"Doe\" },{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" },{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }]}";
        String ivjson = "{\"employees\": [{ \"firstName\":\"John\" ,, \"lastName\":\"Doe\" },{ \"firstName\":\"Anna\" , \"lastName\":\"Smith\" },{ \"firstName\":\"Peter\" , \"lastName\":\"Jones\" }]}";
        System.out.println(""+isValidJson(vjson)); // true
        System.out.println(""+isValidJson(ivjson)); // false
    }

Feito. Aproveitar

Atif Mehar
fonte
0

As respostas estão parcialmente corretas. Eu também enfrentei o mesmo problema. Analisar o json e verificar a exceção parece a maneira usual, mas a solução falha para a entrada json algo como

{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "descendente"} kajhfsadkjh

Como você pode ver, o json é inválido, pois há caracteres de lixo à direita. Mas se você tentar analisar o json acima usando jackson ou gson, obterá o mapa analisado dos caracteres válidos de rastreamento de lixo e json e ignorados. Qual não é a solução necessária quando você está usando o analisador para verificar a validade do json.

Para solução para este problema, veja aqui .

PS: Esta pergunta foi feita e respondida por mim.

iec2011007
fonte
0
import static net.minidev.json.JSONValue.isValidJson;

e então chame essa função passando na sua JSON String :)

Jason
fonte
0
public static boolean isJSONValid(String test) {
    try {
        isValidJSON(test);
        JsonFactory factory = new JsonFactory();
        JsonParser parser = factory.createParser(test);
        while (!parser.isClosed()) {
            parser.nextToken();
        }
    } catch (Exception e) {
        LOGGER.error("exception: ", e);
        return false;
    }
    return true;
}

private static void isValidJSON(String test) {
    try {
        new JSONObject(test);
    } catch (JSONException ex) {
        try {
            LOGGER.error("exception: ", ex);
            new JSONArray(test);
        } catch (JSONException ex1) {
            LOGGER.error("exception: ", ex1);
            throw new Exception("Invalid JSON.");
        }
    }
}

A solução acima abrange os dois cenários:

  • chave duplicada
  • aspas incompatíveis ou parênteses ausentes etc.
Shailendra
fonte
0

Uma solução usando a javax.jsonbiblioteca:

import javax.json.*;

public boolean isTextJson(String text) {
    try {
        Json.createReader(new StringReader(text)).readObject();
    } catch (JsonException ex) {
        try {
            Json.createReader(new StringReader(text)).readArray();
        } catch (JsonException ex2) {
            return false;
        }
    }
    return true;
}
yper
fonte
0

Você pode usar a WellFormedJsonclasse da biblioteca de validação declarativa Validol .

A declaração em si pode ter a seguinte aparência:

new WellFormedJson(
    new Unnamed<>(Either.right(new Present<>(jsonRequestString)))
)

A fase de verificação é assim:

    Result<JsonElement> result =
        (new WellFormedJson(
            new Named<>(
                "vasya",
                Either.right(
                    new Present<>(
                        "{\"guest\":{\"name\":\"Vadim Samokhin\",\"email\":\"[email protected]\"},\"source\":1,\"items\":[{\"id\":1900},{\"id\":777}]}"
                    )
                )
            )
        ))
            .result();

    assertTrue(result.isSuccessful());
    assertEquals(
        "{\"guest\":{\"name\":\"Vadim Samokhin\",\"email\":\"[email protected]\"},\"source\":1,\"items\":[{\"id\":1900},{\"id\":777}]}",
        result.value().raw().toString()
    );
    assertEquals(
        "{\"name\":\"Vadim Samokhin\",\"email\":\"[email protected]\"}",
        result.value().raw().getAsJsonObject().get("guest").toString()
    );

Pode parecer um exagero para uma tarefa tão simples, mas brilha quando você precisa validar uma solicitação complexa. Confira a seção de início rápido do validol .

Vadim Samokhin
fonte