Comment vérifier si une chaîne donnée est un JSON valide en Java

155

Comment valider une chaîne JSON en Java? Ou pourrais-je l'analyser en utilisant des expressions régulières?

sappu
la source
essayez d'analyser avec gson? valider via regex n'est peut-être pas une bonne idée
aishwarya
2
json.org a des liens vers de très nombreux analyseurs
MartinK

Réponses:

261

Une idée sauvage, essayez de l'analyser et attrapez l'exception:

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

Ce code utilise l' implémentation de l' API JSON org.json qui est disponible sur github , dans maven et partiellement sur Android .

MByD
la source
2
Il est proche, mais il manque une validation pour un JSONArray (j'ai mis à jour ce post avec une fonction plus appropriée)
Arthur
9
J'ai essayé une chaîne json comme "{'hello': 'foo'} 'invalid'" (ajouté 'invalid' en dehors de {}), et JSONObject ne lance pas ParseException. J'utilise org.json.JSONObject. Est-ce prévu?
Soichi Hayashi
16
Vous n'avez pas mentionné la bibliothèque contenant JSONObject, je ne l'ai pas vue dans la
librairie
6
Cette solution fonctionne dans la plupart des cas, mais peut échouer dans certaines circonstances. Par exemple, il autorise la virgule juste avant l'accolade fermante, ce qui est en fait une erreur de syntaxe. Reportez-vous à json.org/javadoc/org/json/JSONObject.html pour d'autres cas d'angle.
Hua2308
9
Je ne comprends pas pourquoi les affiches ne peuvent pas être dérangées pour inclure des instructions d'importation avec des extraits de code. C'est important ici. La deuxième réponse ici est bien meilleure.
seansand
100

Bibliothèque JACKSON

Une option serait d'utiliser la bibliothèque Jackson . Importez d'abord la dernière version (maintenant):

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

Ensuite, vous pouvez implémenter la bonne réponse comme suit:

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

Option Google GSON

Une autre option consiste à utiliser Google Gson . Importez la dépendance:

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

Encore une fois, vous pouvez implémenter la solution proposée comme suit:

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

Un test simple suit ici:

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

Veuillez noter qu'il pourrait y avoir un problème "mineur" dû aux virgules de fin qui seront corrigées dans la version 3.0.0.

Jean Valjean
la source
Bien que cela fonctionne pour de grandes choses comme des citations incompatibles ou des parenthèses manquantes, Gson analysera avec plaisir un tableau json avec une virgule à la fin, ce qui n'est pas conforme à la RFC-4627
eurythmia
@eurythmia True! Dans la version 3.0, ils devraient résoudre le problème
JeanValjean
1
Cela valide {key: value} aussi, mais ce n'est pas un json valide
Pratapi Hemant Patel
2
Piège JACKSON: new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")analyse sans exception comme IntNode (28). Pas vraiment attendu ...
mgaert
1
Si je comprends bien, cette solution valide non seulement, mais analyse (et stocke) l'ensemble du fichier json. Il convertit les nombres en Integer / Long / Double etc. C'est plus qu'une simple vérification de syntaxe, il stocke le json entier dans la mémoire. Cela peut être important pour les charges intensives. Si une meilleure solution pour la vérification de la syntaxe existe?
javapowered
15

Avec Google Gson, vous pouvez utiliser JsonParser:

import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Cristian
la source
3
Notez que cela ne génère pas d'erreur sur les chaînes sans crochets ala "asdf"
Andrew
1
Il ne rejette pas non plus les virgules de fin dans les tableaux JSON.
Sotirios Delimanolis
Je ne peux pas vraiment me fier à cela ... il est dit que la chaîne "Save" est analysable.
Dherik
Attention, l'exemple gson utilise ici un mode d'analyse indulgente qui permet encore de nombreux écarts. Voir plus de détails avec testcase et exemple d'analyse stricte dans mes autres réponses.
Vadzim
14

Vous pouvez utiliser le .mayBeJSON (String str) disponible dans la bibliothèque JSONUtils .

npinti
la source
oui ... cela fonctionne. Merci npinti. J'essayais avec gson mais je n'ai vu aucune méthode de ce type.
sappu
@sappu: Si cette réponse a résolu votre question, marquez-la ainsi. La plupart des bibliothèques ont tendance à prendre une chaîne et à essayer de l'analyser.Si l'analyse échoue, c'est-à-dire que la chaîne n'est pas une chaîne JSON valide, elle lèvera une exception.
npinti
@npinti: échec pour extra}. Renvoie vrai pour une chaîne non valide avec un crochet supplémentaire =>}
Vivek
3
Cette méthode vérifie littéralement que la chaîne commence et se termine par des guillemets ou des crochets. Très peu fiable.
Michael Munsey
2
c'est pourquoi le nom de la méthode est «peut-être», pas «est» :)
Khoa
5

Cela dépend de ce que vous essayez de prouver avec votre validation. Il est certain que l'analyse du json, comme d'autres l'ont suggéré, est meilleure que l'utilisation de regex, car la grammaire de json est plus compliquée qu'elle ne peut être représentée avec seulement des regex.

Si le json ne sera jamais analysé que par votre code java, utilisez le même analyseur pour le valider.

Mais l'analyse syntaxique ne vous dira pas nécessairement si elle sera acceptée dans d'autres environnements. par exemple

  • de nombreux analyseurs ignorent les virgules de fin dans un objet ou un tableau, mais les anciennes versions d'IE peuvent échouer lorsqu'elles atteignent une virgule de fin.
  • D'autres analyseurs peuvent accepter une virgule à la fin, mais ajouter une entrée non définie / nulle après.
  • Certains analyseurs peuvent autoriser les noms de propriétés sans guillemets.
  • Certains analyseurs peuvent réagir différemment aux caractères non ASCII dans les chaînes.

Si votre validation doit être très approfondie, vous pouvez:

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

Veuillez télécharger la bibliothèque stringtree-json

Jamsheer
la source
Est-il possible de définir une chaîne comme ci-dessus? Ou c'est juste pour l'idée.
Santron Manibharathi
pas possible, cela était dû à mon
erreur.Maintenant
1
JSONValidatingReader ne fait pas partie de l'API Java
IgorGanapolsky
Veuillez utiliser la bibliothèque mentionnée ci-dessus, merci
Jamsheer
2

Un peu sur l'analyse:

Json, et en fait tous les langages, utilisent une grammaire qui est un ensemble de règles pouvant être utilisées comme substitutions. pour analyser json, vous devez essentiellement travailler sur ces substitutions à l'envers

Json est une grammaire sans contexte , ce qui signifie que vous pouvez avoir des objets / tableaux imbriqués à l'infini et que le json serait toujours valide. regex ne gère que les grammaires régulières (d'où le 'reg' dans le nom), qui est un sous-ensemble de grammaires sans contexte qui ne permettent pas une imbrication infinie, il est donc impossible d'utiliser uniquement regex pour analyser tous les json valides. vous pourriez utiliser un ensemble compliqué de regex et de boucles en supposant que personne ne pourra nicher au-delà, disons, 100 niveaux de profondeur, mais ce serait quand même très difficile.

si vous êtes prêt à écrire votre propre analyseur,
vous pouvez faire un analyseur de descente récursif après avoir travaillé la grammaire

Austin_Anderson
la source
2

Vérifiez si une chaîne donnée est un JSON valide dans Kotlin . J'ai converti la réponse de MByD Java en Kotlin

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

Ici vous pouvez trouver un outil qui peut valider un fichier JSON, ou vous pouvez simplement désérialiser votre fichier JSON avec n'importe quelle bibliothèque JSON et si l'opération réussit, elle devrait être valide ( google-json par exemple qui lèvera une exception si l'entrée il analyse n'est pas JSON valide).

talnicolas
la source
1

En utilisant Playframework 2.6, la bibliothèque Json trouvée dans l'API java peut également être utilisée pour analyser simplement la chaîne. La chaîne peut être un élément json du tableau json. Étant donné que la valeur renvoyée n'a pas d'importance ici, nous détectons simplement l'erreur d'analyse pour déterminer que la chaîne est une chaîne Json correcte ou non.

    import play.libs.Json;

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

À mon humble avis, le moyen le plus élégant consiste à utiliser l' API Java pour le traitement JSON (JSON-P), l'une des normes JavaEE conforme au 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();
}

À l'aide de Maven, ajoutez la dépendance sur JSON-P:

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

Visitez la page officielle JSON-P pour plus d'informations.

Domenico
la source
1

Voici un exemple de travail pour l'analyse stricte de json avec la bibliothèque gson :

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

Voir aussi mon autre réponse détaillée dans Comment vérifier si JSON est valide en Java en utilisant GSON avec plus d'informations et un cas de test étendu avec divers exemples non valides.

Vadzim
la source
1

Comme vous pouvez le voir, il existe de nombreuses solutions, elles analysent principalement le JSON pour le vérifier et à la fin vous devrez l'analyser pour en être sûr.

Mais, selon le contexte, vous pouvez améliorer les performances avec une pré-vérification.

Ce que je fais lorsque j'appelle des API, c'est simplement vérifier que le premier caractère est «{» et le dernier est «}». Si ce n'est pas le cas, je ne prends pas la peine de créer un analyseur.

Orden
la source
0

J'ai trouvé une solution très simple pour cela.

Veuillez d'abord installer cette bibliothèque net.sf.json-libpour cela.

    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
    }

Terminé. Prendre plaisir

Atif Mehar
la source
0

Les réponses sont partiellement correctes. J'ai également rencontré le même problème. L'analyse du json et la vérification de l'exception semble la manière habituelle, mais la solution échoue pour l'entrée json quelque chose comme

{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "décroissant"} kajhfsadkjh

Comme vous pouvez le voir, le json n'est pas valide car il y a des caractères inutiles à la fin. Mais si vous essayez d'analyser le json ci-dessus en utilisant jackson ou gson, vous obtiendrez la carte analysée des json valides et les caractères de fin de garbage sont ignorés. Ce qui n'est pas la solution requise lorsque vous utilisez l'analyseur pour vérifier la validité de json.

Pour une solution à ce problème, voir ici .

PS: Cette question a été posée et répondu par moi.

iec2011007
la source
0
import static net.minidev.json.JSONValue.isValidJson;

puis appelez cette fonction en passant votre chaîne JSON :)

Jason
la source
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 solution ci-dessus couvre les deux scénarios:

  • dupliquer la clé
  • citations incompatibles ou parenthèses manquantes, etc.
Shailendra
la source
0

Une solution utilisant la javax.jsonbibliothèque:

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
la source
0

Vous pouvez utiliser la WellFormedJsonclasse de la bibliothèque de validation déclarative Validol .

La déclaration elle-même pourrait ressembler à ceci:

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

La phase de vérification ressemble à ça:

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

Cela peut sembler exagéré pour une tâche aussi simple, mais cela brille lorsque vous devez valider une demande complexe. Consultez la section de démarrage rapide de validol .

Vadim Samokhin
la source