2013-04-03 13 views
9

Potrzebuję pomocy przy niezawodnym walidatorze string JSON - metodzie, która pobiera ciąg znaków i sprawdza, czy jest to poprawny JSON. Przykład: jeśli przejdę {"color":"red"} lub {"amount":15} przejdzie, ale coś takiego jak "My invalid json" nie będzie. W skrócie potrzebuję czegoś tak niezawodnego jak walidator www.jsonlint.com. BTW - Nie jestem zainteresowany przekształcaniem w obiekt Java, ponieważ nie jest to moim wymaganiem. Mogę otrzymać dowolny ciąg znaków i wszystko, co muszę zrobić, to sprawdzenie, czy ma poprawny format JSON.Niezawodny walidator ciągów JSON w Javie

Mam już zbadane na tym forum kilka postów na ten temat dotyczące walidacji ciągów JSON java.

co zrobiłem do tej pory:

Próbowałem za pomocą tych klas: org.json.JSONObject i org.json.JSONArray w następujący sposób:

private static boolean isValidJSONStringObject(String requestBody){ 
    try { 
     new JSONObject(requestBody); 
    } catch (JSONException jsonEx) { 
     return false; 
    } 
    return true; 
} 

private static boolean isValidJSONStringArray(String requestBody) { 
    try { 
     new JSONArray(requestBody); 
    } catch (JSONException jsonEx) { 
     return false; 
    } 
    return true; 
} 

Jednakże następujące ciągi (cały linie) jeszcze przejść, i nie powinny one:

{"color":"red"}{"var":"value"} 

[1,2,3][true,false] 

innymi słowy, gdy mam obiekty/tablice powtarzane bez wyłapywania jakichkolwiek enkapsulacji w jakimś obiekcie nadrzędnym. Jeśli wkleisz te linie w walidatorze www.jsonlint.com, obydwa zawiodą.

Wiem, że zawsze istnieje opcja regex, ale nie da się tego zagwarantować w 100% ze względu na rekurencyjną naturę JSON, a wyrażenia wyrażenia regularnego będą raczej skomplikowane.

Każda pomoc zostanie bardzo doceniona!

+0

Czy próbowałeś innych bibliotek? Myślę, że jackson na to nie pozwala. – yshavit

+1

'" Mój nieprawidłowy json "' jest złym przykładem nieprawidłowego JSON, ponieważ w rzeczywistości jest prawidłowym łańcuchem JSON. – pfyod

Odpowiedz

6

Gson może sobie z tym poradzić. Oto przykład:

public boolean isValid(String json) { 
    try { 
     new JsonParser().parse(json); 
     return true; 
    } catch (JsonSyntaxException jse) { 
     return false; 
    } 
} 

String json = "{\"color\":\"red\"}{\"var\":\"value\"}"; 
System.out.println(isValid(json)); 

Zauważ, że Gson dopuszcza pewną pobłażliwość w wejściowym JSON, który nie może być pożądany. Na przykład klucze niecytowane są automatycznie konwertowane na cytowane przez analizator składni. To może, ale nie musi, być przełomem w zależności od przewidywanego użycia.

+1

Biblioteka Jacksona nie radzi sobie z tym, chyba że wiesz, do jakiego typu obiektu zamierzasz przekształcić. Ta biblioteka Gsona jest lepsza, ale wydaje się nieco łagodna. Na przykład konwertuje 'abc' na' "abc" 'zamiast wyświetlać błąd. Ale jeśli ograniczysz to, co jest do przyjęcia, po prostu '.isJsonObject()' (metoda 'JsonElement'), to działa dobrze. – Allan

+1

@Allan - Jackson *** can *** parsować JSON bez typu obiektu końcowego (używając na przykład jednej z metod 'readTree'). Ale domyślnie nie raportuje niezawodnie o niepoprawnym JSON.Tryb lojalnościowy Gson jest pod pewnymi względami delikatny, a najnowsze domniemane poprawki błędów najwyraźniej nie są utrzymywane. Dzięki za opinie, zaktualizowałem swoją odpowiedź. – Perception

+0

Tak, biorąc pod uwagę "miękki tryb leniency" parsera gson, zdecydowaliśmy (na razie) uzupełnić parserem jackson, aby spełnić wszystkie nasze wymagania. – rich

3

Oto nasze rozwiązanie na razie. Używanie dwóch różnych bibliotek (gson - pierwsza prywatna metoda i jackson - druga prywatna metoda) nie jest idealne, ale przynajmniej przechodzimy wszystkie nasze testy jednostek/integracji. Założę się, że możemy zrobić wszystko, czego potrzebujemy, używając tylko narzędzi jackson.

public static boolean isStringValidJSON(String jsonString) { 
    return (isJSONStringObjectOrArray(jsonString) && isJSONStringParsable(jsonString)); 
} 

private static boolean isJSONStringObjectOrArray(String jsonString) { 
    try { 
     JsonElement element = new JsonParser().parse(jsonString); 

     return (element.isJsonObject() || element.isJsonArray()); 
    } catch (JsonSyntaxException jsonEx) { 
     return false; 
    } 
} 

private static boolean isJSONStringParsable(String jsonString) { 
    try { 
     org.codehaus.jackson.JsonParser parser = 
      new ObjectMapper().getJsonFactory().createJsonParser(jsonString); 
     while(parser.nextToken() != null) { 
     } 
     return true; 
    } catch (JsonParseException e) { 
     return false; 
    } catch (IOException e) { 
     return false; 
    } 
} 
-3

Wklej ciąg znaków here. Zobacz dane wyjściowe.

EDIT:

Powyższy link już nie działa, this jest dobrą alternatywą.

+2

OP próbuje to programowo. nie za pomocą narzędzia. – SMR

Powiązane problemy