Come verificare se una determinata stringa è JSON valida in Java


155

Come convalido una stringa JSON in Java? O potrei analizzarlo usando espressioni regolari?


prova ad analizzare con gson? la convalida tramite regex potrebbe non essere una buona idea
aishwarya,

2
json.org ha collegamenti a moltissimi parser
MartinK,

Risposte:


261

Un'idea selvaggia, prova ad analizzarla e cogli l'eccezione:

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

Questo codice utilizza l' implementazione dell'API JSON org.json disponibile su github , in maven e parzialmente su Android .


2
È vicino, ma manca una convalida per un JSONArray (ho aggiornato questo post con una funzione più adatta)
Arthur,

9
Ho provato una stringa json come "{'hello': 'foo'} 'invalid'" (aggiunto 'invalid' fuori da {}) e JSONObject non sta lanciando ParseException. Sto usando org.json.JSONObject. È previsto?
Soichi Hayashi,

16
Non hai menzionato una libreria con JSONObject, non l'ho vista nella java lib standard
Krzysztof Krasoń

6
Questa soluzione funziona nella maggior parte dei casi, ma potrebbe non riuscire in determinate circostanze. Ad esempio, consente la virgola proprio prima della parentesi graffa di chiusura, che in realtà è un errore di sintassi. Fare riferimento a json.org/javadoc/org/json/JSONObject.html per altri casi angolari.
Hua2308,

9
Non riesco a capire perché i poster non possano essere disturbati dall'includere dichiarazioni di importazione con frammenti di codice. È importante qui. La risposta di seconda valutazione qui è molto meglio.
seansand,

100

Biblioteca JACKSON

Un'opzione sarebbe quella di utilizzare la libreria Jackson . Prima importa l'ultima versione (ora lo è):

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

Quindi, è possibile implementare la risposta corretta come segue:

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

Opzione Google GSON

Un'altra opzione è utilizzare Google Gson . Importa la dipendenza:

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

Ancora una volta, è possibile implementare la soluzione proposta come:

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

Di seguito è riportato un semplice test:

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

Si prega di notare che potrebbe esserci un problema "minore" a causa delle virgole finali che verranno risolte in fase di rilascio 3.0.0.


Mentre questo funziona per grandi cose come virgolette non corrispondenti o parentesi mancanti, Gson analizzerà felicemente un array json con una virgola finale, che non è conforme a RFC-4627
eurythmia

@eurythmia True! Nella versione 3.0 dovrebbero risolvere il problema
JeanValjean

1
Ciò convalida anche {chiave: valore}, ma non è un json valido
Pratapi Hemant Patel,

2
new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")Trappola di JACKSON: analizza senza eccezione IntNode (28). Non proprio previsto ...
mgaert

1
A quanto ho capito, questa soluzione non solo convalida, ma analizza (e memorizza) l'intero json. Converte i numeri in numeri interi / lunghi / doppi, ecc. Questo è più di un semplice controllo di sintassi, memorizza tutto il json nella memoria. Questo potrebbe essere significativo per carichi intensivi. Se esiste una soluzione migliore per il controllo della sintassi?
javapowered

15

Con Google Gson puoi usare JsonParser:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException

3
Si noti che ciò non genera un errore su stringhe non fissate come "asdf"
Andrew

1
Né rifiuta le virgole finali nelle matrici JSON.
Sotirios Delimanolis,

Non posso davvero fidarmi di questo ... dice che la stringa "Salva" è analizzabile.
Dherik,

Attenzione che esempio GSON usa qui clementi modalità di analisi che consente ancora molte deviazioni. Vedi maggiori dettagli con testcase e rigoroso esempio di analisi nelle mie altre risposte.
Vadzim,

14

È possibile utilizzare .mayBeJSON (String str) disponibile nella libreria JSONUtils .


si ... funziona. Grazie npinti. stavo provando con GSON ma non ho visto alcun metodo simile.
Sappu,

@sappu: se questa risposta ha risolto la tua domanda, contrassegnala così. La maggior parte delle librerie tende a prendere una stringa e tenta di analizzarla, se l'analisi non riesce, ovvero la stringa non è una stringa JSON valida, genererà un'eccezione.
npinti,

@npinti: fallito per extra}. Restituisce vero per stringa non valida con parentesi extra =>}
Vivek

3
Questo metodo controlla letteralmente solo che la stringa inizia e termina con virgolette o parentesi. Molto inaffidabile.
Michael Munsey,

2
ecco perché il nome del metodo è 'forse', non 'è' :)
Khoa

5

Dipende da cosa stai cercando di dimostrare con la tua validazione. Certamente analizzare il json come altri hanno suggerito è meglio che usare regex, perché la grammatica di json è più complicata di quanto possa essere rappresentata con solo regex.

Se il json verrà analizzato solo dal tuo codice java, utilizza lo stesso parser per convalidarlo.

Ma solo l'analisi non ti dirà necessariamente se verrà accettato in altri ambienti. per esempio

  • molti parser ignorano le virgole finali in un oggetto o in un array, ma le versioni precedenti di IE possono fallire quando colpiscono una virgola finale.
  • Altri parser possono accettare una virgola finale, ma aggiungere una voce non definita / null dopo di essa.
  • Alcuni parser possono consentire nomi di proprietà non quotati.
  • Alcuni parser possono reagire in modo diverso ai caratteri non ASCII nelle stringhe.

Se la tua convalida deve essere molto accurata, puoi:


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

Scarica la libreria stringtree-json


È possibile definire una stringa come sopra? O è solo per Idea.
Santron Manibharathi,

impossibile, ciò era dovuto al mio errore. ora è corretto
Grazie

1
JSONValidatingReader non fa parte dell'API Java
IgorGanapolsky

Si prega di utilizzare la libreria di cui sopra, grazie
Jamsheer

2

Un po 'di analisi:

Json, e in effetti tutte le lingue, usano una grammatica che è un insieme di regole che possono essere usate come sostituzioni. al fine di analizzare JSON, è necessario elaborare sostanzialmente quelle sostituzioni al contrario

Json è una grammatica libera dal contesto , il che significa che puoi avere oggetti / array infinitamente nidificati e il json sarebbe comunque valido. regex gestisce solo grammatiche regolari (da qui il 'reg' nel nome), che è un sottoinsieme di grammatiche libere dal contesto che non consente il nesting infinito, quindi è impossibile usare solo regex per analizzare tutti i json validi. potresti usare una serie complicata di regex e loop con il presupposto che nessuno nidificherà oltre, a 100 livelli di profondità, ma sarebbe comunque molto difficile.

se sei pronto per scrivere il tuo parser
potresti creare un parser ricorsivo di discesa dopo aver elaborato la grammatica


2

Controlla se una determinata stringa è JSON valida in Kotlin . Ho convertito la risposta di 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;
}

1

Qui puoi trovare uno strumento in grado di convalidare un file JSON o potresti semplicemente deserializzare il tuo file JSON con qualsiasi libreria JSON e se l'operazione ha esito positivo, dovrebbe essere valida ( ad esempio google-json genererà un'eccezione se l'input sta analizzando non è valido JSON).


1

Usando Playframework 2.6, la libreria Json trovata in java api può anche essere usata per analizzare semplicemente la stringa. La stringa può essere un elemento json dell'array json. Poiché il valore restituito non è importante qui, viene rilevato l'errore di analisi per determinare se la stringa è una stringa JSON corretta o meno.

    import play.libs.Json;

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

1

IMHO, il modo più elegante è utilizzare l' API Java per l'elaborazione JSON (JSON-P), uno degli standard JavaEE conforme a 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();
}

Utilizzando Maven, aggiungi la dipendenza da JSON-P:

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

Visita la pagina ufficiale JSON-P per maggiori informazioni.


1

Ecco un esempio funzionante per l'analisi json rigorosa con la libreria gson :

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

Vedi anche la mia altra risposta dettagliata in Come verificare se JSON è valido in Java usando GSON con maggiori informazioni e case test esteso con vari esempi non validi.


1

Come puoi vedere, ci sono molte soluzioni, principalmente analizzano il JSON per verificarlo e alla fine dovrai analizzarlo per sicurezza.

Ma, a seconda del contesto, è possibile migliorare le prestazioni con un controllo preliminare.

Quello che faccio quando chiamo API, è solo verificare che il primo carattere sia "{" e l'ultimo sia "}". In caso contrario, non mi preoccupo di creare un parser.


0

Ho trovato una soluzione molto semplice per questo.

Si prega di installare prima questa libreria net.sf.json-libper questo.

    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
    }

Fatto. Godere


0

Le risposte sono parzialmente corrette. Ho anche affrontato lo stesso problema. Analizzare il json e verificare l'eccezione sembra il solito, ma la soluzione non riesce per l'input json in qualcosa del genere

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

Come puoi vedere, il json non è valido perché ci sono caratteri di immondizia finali. Ma se provi ad analizzare il json sopra usando jackson o gson, otterrai la mappa analizzata del json valido e i caratteri finali dell'immondizia vengono ignorati. Quale non è la soluzione richiesta quando si utilizza il parser per verificare la validità di JSON.

Per la soluzione a questo problema, vedere qui .

PS: questa domanda mi è stata posta e ho risposto.


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

e quindi chiama questa funzione passando nella tua stringa JSON :)


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 soluzione precedente copre entrambi gli scenari:

  • chiave duplicata
  • virgolette non corrispondenti o parentesi mancanti ecc.

0

Una soluzione che utilizza la javax.jsonlibreria:

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

0

È possibile utilizzare la WellFormedJsonclasse dalla libreria di convalida dichiarativa Validol .

La stessa dichiarazione potrebbe essere simile alla seguente:

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

La fase di controllo si presenta così:

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

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

Potrebbe sembrare eccessivo per un'attività così semplice, ma brilla quando devi convalidare una richiesta complessa. Dai un'occhiata alla sezione di avvio rapido di validol .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.