Jak sprawdzić poprawność ciągu JSON w Javie? A może mógłbym przeanalizować go przy użyciu wyrażeń regularnych?
Jak sprawdzić poprawność ciągu JSON w Javie? A może mógłbym przeanalizować go przy użyciu wyrażeń regularnych?
Odpowiedzi:
Dziki pomysł, spróbuj go przeanalizować i wyłap wyjątek:
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;
}
Ten kod wykorzystuje implementację JSON API org.json, która jest dostępna na github , w maven i częściowo w systemie Android .
Biblioteka JACKSON
Jedną z opcji byłoby skorzystanie z biblioteki Jacksona . Najpierw zaimportuj najnowszą wersję (teraz jest):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
Następnie możesz zaimplementować poprawną odpowiedź w następujący sposób:
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;
}
}
}
Opcja Google GSON
Inną opcją jest użycie Google Gson . Zaimportuj zależność:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.5</version>
</dependency>
Ponownie możesz zaimplementować proponowane rozwiązanie jako:
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;
}
}
}
Oto prosty 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
Proszę zauważyć, że może wystąpić „drobny” problem związany z końcowymi przecinkami, który zostanie naprawiony w wydaniu 3.0.0
.
new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")
Pułapka JACKSON: analizuje bez wyjątku jako IntNode (28). Niezupełnie oczekiwane ...
Dzięki Google Gson możesz użyć JsonParser:
import com.google.gson.JsonParser;
JsonParser parser = new JsonParser();
parser.parse(json_string); // throws JsonSyntaxException
Możesz użyć .mayBeJSON (String str) dostępnego w bibliotece JSONUtils .
To zależy od tego, co próbujesz udowodnić w ramach walidacji. Z pewnością przeanalizowanie json, jak sugerowali inni, jest lepsze niż użycie wyrażeń regularnych, ponieważ gramatyka json jest bardziej skomplikowana niż można ją przedstawić za pomocą samych wyrażeń regularnych.
Jeśli json będzie kiedykolwiek analizowany tylko przez twój kod java, użyj tego samego parsera, aby go zweryfikować.
Ale samo przeanalizowanie niekoniecznie powie Ci, czy zostanie zaakceptowane w innych środowiskach. na przykład
Jeśli Twoja walidacja musi być bardzo dokładna, możesz:
String jsonInput = "{\"mob no\":\"9846716175\"}";//Read input Here
JSONReader reader = new JSONValidatingReader();
Object result = reader.read(jsonInput);
System.out.println("Validation Success !!");
Proszę pobrać bibliotekę stringtree-json
Trochę o parsowaniu:
Json, a właściwie wszystkie języki, używają gramatyki, która jest zestawem reguł, których można używać jako podstawień. aby przeanalizować json, musisz w zasadzie wypracować te podstawienia w odwrotnej kolejności
Json to gramatyka bezkontekstowa , co oznacza, że możesz mieć nieskończenie zagnieżdżone obiekty / tablice, a json nadal będzie prawidłowy. regex obsługuje tylko regularne gramatyki (stąd „reg” w nazwie), które są podzbiorem gramatyk bezkontekstowych, które nie pozwalają na nieskończone zagnieżdżanie, więc niemożliwe jest użycie tylko wyrażenia regularnego do przeanalizowania wszystkich prawidłowych plików json. możesz użyć skomplikowanego zestawu wyrażeń regularnych i pętli, zakładając, że nikt nie zagnieździ się powyżej, powiedzmy, 100 poziomów głębokości, ale nadal byłoby to bardzo trudne.
jeśli masz ochotę napisać swój własny parser,
możesz po opanowaniu gramatyki stworzyć rekurencyjny parser zstępujący
Sprawdź, czy podany ciąg jest prawidłowym JSON w Kotlinie . Przekonwertowałem odpowiedź MByD Java na Kotlin
fun isJSONValid(test: String): Boolean {
try {
JSONObject(test);
} catch (ex: JSONException) {
try {
JSONArray(test);
} catch (ex1: JSONException) {
return false;
}
}
return true;
}
Tutaj możesz znaleźć narzędzie, które może zweryfikować plik JSON lub po prostu deserializować plik JSON za pomocą dowolnej biblioteki JSON i jeśli operacja się powiedzie, to powinno być poprawne ( na przykład google-json , które wyrzuci wyjątek, jeśli dane wejściowe to analizowanie nie jest prawidłowym formatem JSON).
Korzystając z Playframework 2.6, można również użyć biblioteki Json znajdującej się w api Java, aby po prostu przeanalizować ciąg. Ciąg może być elementem json tablicy json. Ponieważ zwracana wartość nie ma tutaj znaczenia, po prostu przechwytujemy błąd analizy, aby określić, czy ciąg jest prawidłowym ciągiem json, czy nie.
import play.libs.Json;
public static Boolean isValidJson(String value) {
try{
Json.parse(value);
return true;
} catch(final Exception e){
return false;
}
}
IMHO, najbardziej eleganckim sposobem jest użycie Java API for JSON Processing (JSON-P), jednego ze standardów JavaEE, który jest zgodny z 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();
}
Używając Maven, dodaj zależność od JSON-P:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1.4</version>
</dependency>
Odwiedź oficjalną stronę JSON-P, aby uzyskać więcej informacji.
Oto działający przykład ścisłego parsowania json z biblioteką gson :
public static JsonElement parseStrict(String json) {
// throws on almost any non-valid json
return new Gson().getAdapter(JsonElement.class).fromJson(json);
}
Zobacz także moją inną szczegółową odpowiedź w artykule Jak sprawdzić, czy JSON jest poprawny w Javie przy użyciu GSON z dodatkowymi informacjami i rozszerzonym przypadkiem testowym z różnymi nieprawidłowymi przykładami.
Jak widać, rozwiązań jest sporo, głównie parsują one JSON, żeby to sprawdzić i na koniec trzeba będzie go przeanalizować, żeby mieć pewność.
Jednak w zależności od kontekstu można poprawić wydajność, sprawdzając wstępnie.
Kiedy wywołuję interfejsy API, po prostu sprawdzam, czy pierwszy znak to „{”, a ostatni to „}”. Jeśli tak nie jest, nie zawracam sobie głowy tworzeniem parsera.
Znalazłem na to bardzo proste rozwiązanie.
Najpierw zainstaluj net.sf.json-lib
dla niego tę bibliotekę .
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
}
Gotowe. Cieszyć się
Odpowiedzi są częściowo poprawne. Ja też stanąłem przed tym samym problemem. Przetwarzanie json i sprawdzanie wyjątku wydaje się zwykłym sposobem, ale rozwiązanie nie działa w przypadku wejściowego pliku JSON, podobnie jak
{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "descending"} kajhfsadkjh
Jak widać, plik json jest nieprawidłowy, ponieważ zawiera końcowe znaki śmieci. Ale jeśli spróbujesz przeanalizować powyższy json za pomocą json lub gson, otrzymasz przeanalizowaną mapę prawidłowych json, a znaki końcowe json są ignorowane. Co nie jest wymaganym rozwiązaniem, gdy używasz parsera do sprawdzania poprawności json.
Rozwiązanie tego problemu znajdziesz tutaj .
PS: To pytanie zadałem i odpowiedziałem.
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.");
}
}
}
Powyższe rozwiązanie obejmuje oba scenariusze:
Rozwiązanie wykorzystujące javax.json
bibliotekę:
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;
}
Możesz użyć WellFormedJson
klasy z biblioteki walidacji deklaratywnej Validol .
Sama deklaracja mogłaby wyglądać następująco:
new WellFormedJson(
new Unnamed<>(Either.right(new Present<>(jsonRequestString)))
)
Faza sprawdzania wygląda następująco:
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()
);
Może się to wydawać przesadą w przypadku tak prostego zadania, ale sprawdza się, gdy trzeba zweryfikować złożone żądanie. Sprawdź sekcję szybkiego startu validol .