Cómo verificar si una cadena dada es JSON válida en Java

155

¿Cómo valido una cadena JSON en Java? ¿O podría analizarlo usando expresiones regulares?

sappu
fuente
intente analizar con gson? validar a través de regex puede no ser una buena idea
aishwarya
2
json.org tiene enlaces a muchos analizadores
MartinK

Respuestas:

261

Una idea descabellada, intenta analizarla y detecta la excepción:

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;
}

Este código utiliza la implementación de la API JSON org.json que está disponible en github , en maven y parcialmente en Android .

MByD
fuente
2
Está cerca, pero le falta una validación para un JSONArray (he actualizado esta publicación con una función más adecuada)
Arthur
9
He intentado una cadena json como "{'hola': 'foo'} 'inválido'" (agregado 'inválido' fuera de {}), y JSONObject no está lanzando ParseException. Estoy usando org.json.JSONObject. ¿Se espera esto?
Soichi Hayashi
16
No mencionaste la biblioteca que tiene JSONObject, no la vi en la versión estándar de Java
Krzysztof Krasoń
66
Esta solución funciona para la mayoría de los casos, pero podría fallar en ciertas circunstancias. Por ejemplo, permite la coma justo antes de la llave de cierre, que en realidad es un error de sintaxis. Consulte json.org/javadoc/org/json/JSONObject.html para otros casos de esquina.
Hua2308
9
No puedo entender por qué los pósters no pueden molestarse en incluir declaraciones de importación con fragmentos de código. Es importante aquí La segunda respuesta aquí es mucho mejor.
seansand
100

Biblioteca JACKSON

Una opción sería usar la biblioteca Jackson . Primero importe la última versión (ahora es):

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

Luego, puede implementar la respuesta correcta de la siguiente manera:

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;
    }
  }
}

Opción GSON de Google

Otra opción es usar Google Gson . Importar la dependencia:

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

Nuevamente, puede implementar la solución propuesta 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;
      }
  }
}

Una prueba simple sigue aquí:

//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

Tenga en cuenta que podría haber un problema "menor" debido a las comas finales que se solucionarán en el lanzamiento 3.0.0.

JeanValjean
fuente
Si bien esto funciona para grandes cosas como citas no coincidentes o paréntesis faltantes, Gson analizará felizmente una matriz json con una coma final, que no cumple con RFC-4627
euritmia
@eurythmia cierto! En la versión 3.0 deberían solucionar el problema
JeanValjean
1
Esto valida {clave: valor} también, pero no es un json válido
Pratapi Hemant Patel
2
Dificultad de JACKSON: new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")analiza sin excepción como IntNode (28). Realmente no se esperaba ...
mgaert
1
Según tengo entendido, esta solución no solo valida, sino que analiza (y almacena) todo el json. Convierte números a Entero / Largo / Doble, etc. Esto es más que una simple verificación de sintaxis, almacena todo json en la memoria. Esto puede ser significativo para cargas intensivas. Si existe una mejor solución para la verificación de sintaxis?
Java el
15

Con Google Gson puedes usar JsonParser:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Cristian
fuente
3
Tenga en cuenta que esto no arroja un error en cadenas sin corchetes ala "asdf"
Andrew
1
Tampoco rechaza las comas finales en las matrices JSON.
Sotirios Delimanolis
Realmente no puedo confiar en eso ... dice que la cadena "Guardar" es analizable.
Dherik
Tenga en cuenta que el ejemplo de gson aquí usa un modo de análisis indulgente que aún permite muchas desviaciones. Vea más detalles con el caso de prueba y el ejemplo de análisis estricto en mis otras respuestas.
Vadzim
14

Puede usar el .mayBeJSON (String str) disponible en la biblioteca JSONUtils .

npinti
fuente
Sí ... esto está funcionando. Gracias npinti Estaba intentando con gson pero no había tal método que haya visto.
sappu
@sappu: Si esta respuesta resolvió su pregunta, márquela así. La mayoría de las bibliotecas tienden a tomar una Cadena e intentar analizarla, si el análisis falla, es decir, la cadena no es una cadena JSON válida, arrojará una excepción.
npinti
@npinti: no se pudo obtener más}. Devuelve verdadero para una cadena no válida con un paréntesis adicional =>}
Vivek
3
Este método literalmente solo verifica que la cadena comience y termine con comillas o corchetes. Muy poco confiable.
Michael Munsey
2
por eso el nombre del método es 'quizás', no 'es' :)
Khoa
5

Depende de lo que intente probar con su validación. Ciertamente, analizar el json como otros han sugerido es mejor que usar expresiones regulares, porque la gramática de json es más complicada de lo que se puede representar con expresiones regulares.

Si su código java solo analizará el json, use el mismo analizador para validarlo.

Pero solo el análisis no necesariamente le dirá si será aceptado en otros entornos. p.ej

  • muchos analizadores ignoran las comas finales en un objeto o matriz, pero las versiones antiguas de IE pueden fallar cuando tocan una coma final.
  • Otros analizadores pueden aceptar una coma final, pero agregan una entrada indefinida / nula después.
  • Algunos analizadores pueden permitir nombres de propiedades sin comillas.
  • Algunos analizadores pueden reaccionar de manera diferente a caracteres no ASCII en cadenas.

Si su validación debe ser muy exhaustiva, podría:

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

Descargue la biblioteca stringtree-json

Jamsheer
fuente
¿Es posible definir una cadena como la anterior? O es solo para Idea.
Santron Manibharathi
no es posible, eso se debió a mi error. ahora está corregido
Gracias
1
JSONValidatingReader no es parte de la API de Java
IgorGanapolsky
Utilice la biblioteca mencionada anteriormente, gracias
Jamsheer
2

Un poco sobre el análisis:

Json, y de hecho todos los idiomas, usan una gramática que es un conjunto de reglas que pueden usarse como sustituciones. para analizar json, básicamente necesitas resolver esas sustituciones a la inversa

Json es una gramática libre de contexto , lo que significa que puede tener objetos / matrices anidados infinitamente y el json aún sería válido. regex solo maneja gramáticas regulares (de ahí el 'reg' en el nombre), que es un subconjunto de gramáticas libres de contexto que no permite anidamiento infinito, por lo que es imposible usar solo regex para analizar todos los json válidos. podría usar un conjunto complicado de expresiones regulares y bucles con la suposición de que nadie anidará más allá de, digamos, 100 niveles de profundidad, pero aún sería muy difícil.

si estás listo para escribir tu propio analizador,
puedes hacer un analizador de descenso recursivo después de resolver la gramática

Austin_Anderson
fuente
2

Compruebe si una cadena dada es JSON válida en Kotlin . Convertí la respuesta de MByD Java a Kotlin

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

Aquí puede encontrar una herramienta que puede validar un archivo JSON, o simplemente puede deserializar su archivo JSON con cualquier biblioteca JSON y si la operación es exitosa, entonces debería ser válida ( google-json, por ejemplo, arrojará una excepción si la entrada está analizando no es válido JSON).

talnicolas
fuente
1

Usando Playframework 2.6, la biblioteca Json que se encuentra en la API de Java también se puede usar para analizar simplemente la cadena. La cadena puede ser un elemento json de la matriz json. Dado que el valor devuelto no es importante aquí, solo detectamos el error de análisis para determinar que la cadena es una cadena json correcta o no.

    import play.libs.Json;

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

En mi humilde opinión, la forma más elegante es utilizar la API de Java para el procesamiento JSON (JSON-P), uno de los estándares JavaEE que se ajusta al 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 Maven, agregue la dependencia en JSON-P:

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

Visite la página oficial de JSON-P para obtener más información.

Domenico
fuente
1

Aquí hay un ejemplo de trabajo para analizar estrictamente json con la biblioteca gson :

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

Vea también mi otra respuesta detallada en Cómo verificar si JSON es válido en Java usando GSON con más información y un caso de prueba extendido con varios ejemplos no válidos.

Vadzim
fuente
1

Como puede ver, hay muchas soluciones, principalmente analizan el JSON para verificarlo y al final tendrá que analizarlo para asegurarse.

Pero, dependiendo del contexto, puede mejorar las actuaciones con una verificación previa.

Lo que hago cuando llamo a las API es comprobar que el primer carácter es '{' y el último es '}'. Si no es el caso, no me molesto en crear un analizador.

Orden
fuente
0

He encontrado una solución muy simple para ello.

Primero instale esta biblioteca net.sf.json-libpara ello.

    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
    }

Hecho. Disfrutar

Atif Mehar
fuente
0

Las respuestas son parcialmente correctas. También enfrenté el mismo problema. Analizar el json y buscar excepciones parece la forma habitual, pero la solución falla para la entrada json algo así como

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

Como puede ver, el json no es válido ya que hay caracteres de basura al final. Pero si intenta analizar el json anterior usando jackson o gson, obtendrá el mapa analizado de los caracteres válidos json y basura que se ignoran. Cuál no es la solución requerida cuando está utilizando el analizador para verificar la validez de json.

Para la solución a este problema, ver aquí .

PD: Esta pregunta fue formulada y respondida por mí.

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

y luego llame a esta función pasando su cadena JSON :)

Jason
fuente
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.");
        }
    }
}

La solución anterior cubre ambos escenarios:

  • llave duplicada
  • citas no coincidentes o paréntesis faltantes, etc.
Shailendra
fuente
0

Una solución usando la 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;
}
sip
fuente
0

Puede usar la WellFormedJsonclase de la biblioteca de validación declarativa Validol .

La declaración en sí podría tener el siguiente aspecto:

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

La fase de verificación se ve así:

    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()
    );

Puede parecer una exageración para una tarea tan simple, pero brilla cuando tienes que validar una solicitud compleja. Consulte la sección de inicio rápido de validol .

Vadim Samokhin
fuente