So überprüfen Sie, ob eine bestimmte Zeichenfolge in Java als JSON gültig ist

155

Wie überprüfe ich eine JSON-Zeichenfolge in Java? Oder könnte ich es mit regulären Ausdrücken analysieren?

Sappu
quelle
versuchen Sie es mit Gson zu analysieren? Validierung durch Regex ist möglicherweise keine gute Idee
Aishwarya
2
json.org hat Links zu sehr vielen Parsern
MartinK

Antworten:

261

Eine wilde Idee, versuchen Sie es zu analysieren und fangen Sie die Ausnahme:

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

Dieser Code verwendet die JSON-API-Implementierung von org.json , die auf github , in maven und teilweise auf Android verfügbar ist .

MByD
quelle
2
Es ist nah, aber es fehlt eine Validierung für ein JSONArray (ich habe diesen Beitrag mit einer geeigneteren Funktion aktualisiert)
Arthur
9
Ich habe einen JSON-String wie "{'hello': 'foo'} 'invalid'" ausprobiert ('invalid' außerhalb von {} hinzugefügt), und JSONObject löst keine ParseException aus. Ich benutze org.json.JSONObject. Wird das erwartet?
Soichi Hayashi
16
Sie haben keine Bibliothek mit JSONObject erwähnt, ich habe sie nicht in der Standard-Java-Bibliothek gesehen
Krzysztof Krasoń
6
Diese Lösung funktioniert in den meisten Fällen, kann jedoch unter bestimmten Umständen fehlschlagen. Beispielsweise wird das Komma direkt vor der schließenden Klammer zugelassen, was eigentlich ein Syntaxfehler ist. Weitere Eckfälle finden Sie unter json.org/javadoc/org/json/JSONObject.html .
Hua2308
9
Ich kann nicht verstehen, warum Poster nicht die Mühe haben, Importanweisungen mit Codefragmenten zu versehen. Das ist hier wichtig. Die zweitbewertete Antwort hier ist viel besser.
Sean und
100

JACKSON Bibliothek

Eine Möglichkeit wäre die Verwendung der Jackson-Bibliothek . Importieren Sie zuerst die neueste Version (jetzt ist):

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

Anschließend können Sie die richtige Antwort wie folgt implementieren :

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

Google GSON-Option

Eine andere Option ist zu verwenden Google Gson . Importieren Sie die Abhängigkeit:

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

Auch hier können Sie die vorgeschlagene Lösung wie folgt implementieren:

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

Hier folgt ein einfacher 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

Bitte beachten Sie, dass aufgrund von Kommas, die in der Version behoben werden, ein "geringfügiges" Problem auftreten kann 3.0.0.

Jean Valjean
quelle
Während dies für große Dinge wie nicht übereinstimmende Anführungszeichen oder fehlende Klammern funktioniert, analysiert Gson gerne ein JSON-Array mit einem nachgestellten Komma, das nicht mit RFC-4627 übereinstimmt
Eurythmie
@ eurythmia Stimmt! In Version 3.0 sollten sie das Problem beheben
JeanValjean
1
Dies validiert auch {key: value}, aber es ist kein gültiger json
Pratapi Hemant Patel
2
new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")JACKSON-Falle : Analysiert ohne Ausnahme als IntNode (28). Nicht wirklich erwartet ...
mgaert
1
Soweit ich weiß, validiert (und speichert) diese Lösung nicht nur den gesamten JSON. Es konvertiert Zahlen in Integer / Long / Double usw. Dies ist mehr als nur eine Syntaxprüfung, es speichert den gesamten JSON im Speicher. Dies kann bei intensiven Belastungen von Bedeutung sein. Gibt es eine bessere Lösung für die Syntaxprüfung?
Javapowered
15

Mit Google Gson können Sie JsonParser verwenden:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Cristian
quelle
3
Beachten Sie, dass dies keinen Fehler auf nicht geknackten Zeichenfolgen ala "asdf"
Andrew
1
Nachfolgende Kommas in JSON-Arrays werden ebenfalls nicht abgelehnt.
Sotirios Delimanolis
Darauf kann ich nicht wirklich vertrauen ... es heißt, dass die Zeichenfolge "Speichern" analysierbar ist.
Dherik
Beachten Sie, dass das gson-Beispiel hier verwendet nachsichtig Parsing - Modus , die noch viele Abweichungen erlaubt. Sehen Sie weitere Informationen mit Testfall und strengem Parsing Beispiel in meinen anderen Antworten.
Vadzim
14

Sie können die in der JSONUtils- Bibliothek verfügbare .mayBeJSON (String str) verwenden.

npinti
quelle
ja ... das funktioniert. Danke npinti. Ich habe es mit Gson versucht, aber es gibt keine solche Methode, die ich gesehen habe.
Sappu
@sappu: Wenn diese Antwort Ihre Frage gelöst hat, markieren Sie sie so. Die meisten Bibliotheken neigen dazu, eine Zeichenfolge aufzunehmen und zu analysieren. Wenn die Analyse fehlschlägt, dh die Zeichenfolge keine gültige JSON-Zeichenfolge ist, wird eine Ausnahme ausgelöst.
Npinti
@npinti: Fehlgeschlagen für extra}. Gibt true für eine ungültige Zeichenfolge mit zusätzlicher Klammer zurück =>}
Vivek
3
Diese Methode überprüft buchstäblich nur, ob die Zeichenfolge mit Anführungszeichen oder Klammern beginnt und endet. Sehr unzuverlässig.
Michael Munsey
2
Deshalb ist der Methodenname 'vielleicht', nicht 'ist' :)
Khoa
5

Dies hängt davon ab, was Sie mit Ihrer Validierung beweisen möchten. Das Parsen des JSON, wie andere vorgeschlagen haben, ist sicherlich besser als die Verwendung von Regexen, da die Grammatik von Json komplizierter ist, als dies nur mit Regexen dargestellt werden kann.

Wenn der JSON immer nur von Ihrem Java-Code analysiert wird, verwenden Sie denselben Parser, um ihn zu validieren.

Nur das Parsen sagt Ihnen jedoch nicht unbedingt, ob es in anderen Umgebungen akzeptiert wird. z.B

  • Viele Parser ignorieren nachgestellte Kommas in einem Objekt oder Array, aber alte Versionen des IE können fehlschlagen, wenn sie nach einem Komma stehen.
  • Andere Parser akzeptieren möglicherweise ein nachfolgendes Komma, fügen danach jedoch einen undefinierten / null-Eintrag hinzu.
  • Einige Parser erlauben möglicherweise nicht zitierte Eigenschaftsnamen.
  • Einige Parser reagieren möglicherweise anders auf Nicht-ASCII-Zeichen in Zeichenfolgen.

Wenn Ihre Validierung sehr gründlich sein muss, können Sie:

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

Bitte laden Sie die Bibliothek stringtree-json herunter

Jamsheer
quelle
Ist es möglich, einen String wie oben zu definieren? Oder es ist nur für die Idee.
Santron Manibharathi
nicht möglich, das lag an meinem Fehler. Jetzt ist es korrigiert.
Danke
1
JSONValidatingReader ist nicht Teil der Java API
IgorGanapolsky
Bitte benutzen Sie die oben genannte Bibliothek, Danke
Jamsheer
2

Ein bisschen über das Parsen:

Json und tatsächlich alle Sprachen verwenden eine Grammatik der es sich um eine Reihe von Regeln handelt, die als Substitutionen verwendet werden können. Um json zu analysieren, müssen Sie diese Substitutionen grundsätzlich umgekehrt berechnen

Json ist eine kontextfreie Grammatik , dh Sie können unendlich verschachtelte Objekte / Arrays haben und der Json wäre weiterhin gültig. Regex behandelt nur reguläre Grammatiken (daher das 'reg' im Namen), eine Teilmenge kontextfreier Grammatiken, die keine unendliche Verschachtelung zulassen. Daher ist es unmöglich, nur Regex zum Parsen aller gültigen JSON zu verwenden. Sie könnten einen komplizierten Satz von Regexs und Schleifen verwenden, mit der Annahme, dass niemand vorbei nisten wird, sagen wir 100 Level tief, aber es wäre immer noch sehr schwierig.

Wenn Sie bereit sind, Ihren eigenen Parser zu schreiben, können
Sie nach dem Ausarbeiten der Grammatik einen rekursiven Abstiegsparser erstellen

Austin_Anderson
quelle
2

Überprüfen Sie, ob eine bestimmte Zeichenfolge in Kotlin als JSON gültig ist . Ich habe die Antwort von MByD Java in Kotlin konvertiert

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

Hier finden Sie ein Tool , mit dem eine JSON-Datei validiert werden kann, oder Sie können Ihre JSON-Datei einfach mit einer beliebigen JSON-Bibliothek deserialisieren. Wenn der Vorgang erfolgreich ist, sollte sie gültig sein ( z. B. google-json , das bei der Eingabe eine Ausnahme auslöst es ist parsing ist nicht gültig JSON).

Talnicolas
quelle
1

Mit Playframework 2.6 kann die in der Java-API enthaltene Json-Bibliothek auch zum einfachen Parsen der Zeichenfolge verwendet werden. Die Zeichenfolge kann entweder ein JSON-Element des JSON-Arrays sein. Da der zurückgegebene Wert hier nicht von Bedeutung ist, wird nur der Analysefehler abgefangen, um festzustellen, ob die Zeichenfolge eine korrekte JSON-Zeichenfolge ist oder nicht.

    import play.libs.Json;

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

IMHO ist die eleganteste Methode die Verwendung der Java-API für die JSON-Verarbeitung (JSON-P), einem der JavaEE-Standards, die dem JSR 374 entsprechen .

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

Fügen Sie mit Maven die Abhängigkeit von JSON-P hinzu:

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

Besuchen Sie die offizielle JSON-P-Seite für weitere Informationen.

Domenico
quelle
1

Hier ist ein funktionierendes Beispiel für die strikte Analyse von JSON mit der Gson- Bibliothek:

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

Siehe auch meine andere ausführliche Antwort unter So überprüfen Sie, ob JSON in Java mit GSON gültig ist, mit weiteren Informationen und einem erweiterten Testfall mit verschiedenen ungültigen Beispielen.

Vadzim
quelle
1

Wie Sie sehen können, gibt es viele Lösungen. Sie analysieren hauptsächlich den JSON, um ihn zu überprüfen, und am Ende müssen Sie ihn analysieren, um sicherzugehen.

Je nach Kontext können Sie die Leistung jedoch durch eine Vorabprüfung verbessern.

Wenn ich APIs aufrufe, überprüfe ich nur, ob das erste Zeichen '{' und das letzte '}' ist. Wenn dies nicht der Fall ist, erstelle ich keinen Parser.

Orden
quelle
0

Ich habe eine sehr einfache Lösung dafür gefunden.

Bitte installieren Sie zuerst diese Bibliothek net.sf.json-libdafür.

    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
    }

Getan. Genießen

Atif Mehar
quelle
0

Die Antworten sind teilweise richtig. Ich hatte auch das gleiche Problem. Das Parsen des JSON und das Überprüfen auf Ausnahmen scheint die übliche Methode zu sein, aber die Lösung schlägt für den Eingabe-JSON so etwas wie fehl

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

Wie Sie sehen können, ist der JSON ungültig, da nachgestellte Garbage-Zeichen vorhanden sind. Wenn Sie jedoch versuchen, den obigen JSON mit Jackson oder GSON zu analysieren, wird die analysierte Karte des gültigen JSON angezeigt, und die nachgestellten Garbage-Zeichen werden ignoriert. Dies ist nicht die erforderliche Lösung, wenn Sie den Parser zur Überprüfung der JSON-Gültigkeit verwenden.

Eine Lösung für dieses Problem finden Sie hier .

PS: Diese Frage wurde von mir gestellt und beantwortet.

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

und rufen Sie dann diese Funktion auf, die Ihren JSON-String übergibt :)

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

Die obige Lösung deckt beide Szenarien ab:

  • Zweitschlüssel
  • Nicht übereinstimmende Anführungszeichen oder fehlende Klammern usw.
Shailendra
quelle
0

Eine Lösung mit der javax.jsonBibliothek:

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
quelle
0

Sie können eine WellFormedJsonKlasse aus der deklarativen Validol- Validierungsbibliothek verwenden.

Die Erklärung selbst könnte wie folgt aussehen:

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

Die Prüfphase sieht folgendermaßen aus:

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

Es mag wie ein Overkill für eine so einfache Aufgabe erscheinen, aber es leuchtet, wenn Sie eine komplexe Anfrage validieren müssen. Schauen Sie sich den Schnellstartabschnitt von validol an .

Vadim Samokhin
quelle