Як перевірити, чи дана строка є дійсною JSON на Java


155

Як перевірити рядок JSON на Java? Або я міг би її розібрати, використовуючи регулярні вирази?


спробувати розібратися з gson? перевірка через регулярний вираз може бути не дуже хорошою ідеєю
aishwarya

2
json.org має посилання на дуже багато парсерів
MartinK

Відповіді:


261

Дика ідея, спробуйте її розібрати і вилучити виняток:

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

У цьому коді використовується org.json JSON API-реалізація, яка доступна в github , в maven та частково на Android .


2
Він близький, але відсутня перевірка для JSONArray (я оновив цю посаду з більш підходящою функцією)
Артур

9
Я спробував рядок json на зразок "{'hello': 'foo'} 'invalid'" (додано "invalid" за межами {}), і JSONObject не кидає ParseException. Я використовую org.json.JSONObject. Це очікується?
Soichi Hayashi

16
Ви не згадали про бібліотеку, яка має JSONObject, я її не бачив у стандартній java lib
Krzysztof Krasoń

6
Це рішення працює в більшості випадків, але може вийти з ладу за певних обставин. Наприклад, це дозволяє кома безпосередньо перед дужкою, що закривається, що насправді є синтаксичною помилкою. Інші кутові випадки див. На json.org/javadoc/org/json/JSONObject.html .
Hua2308

9
Я не можу зрозуміти, чому плакатам не можна заважати включати заяви про імпорт із фрагментами коду. Тут важливо. Другозначна відповідь тут набагато краща.
seansand

100

JACKSON Бібліотека

Одним із варіантів було б використання бібліотеки Джексона . Спочатку імпортуйте останню версію (зараз є):

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

Тоді ви можете реалізувати правильну відповідь так:

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

Інший варіант - використовувати Google Gson . Імпортуйте залежність:

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

Знову ж, ви можете реалізувати запропоноване рішення як:

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

Тут простий тест:

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

Будь ласка, зауважте, що може виникнути "незначна" проблема через затримки коми, які будуть виправлені у звільненні 3.0.0.


Хоча це працює для великих речей, таких як невідповідні цитати або відсутні дужки, Gson із задоволенням розбере масив json з комою, що не відповідає стандарту RFC-4627
eurythmia

@eurythmia Щоправда! У версії 3.0 вони повинні виправити проблему
JeanValjean

1
Це підтверджує і {ключ: значення}, але його недійсний json
Pratapi Hemant Patel

2
new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")JAKKSON pitfall : аналізує без винятку розбір як IntNode (28). Насправді не очікували ...
mgaert

1
Як я розумію, це рішення не тільки перевіряє, але аналізує (і зберігає) весь json. Він перетворює числа в Integer / Long / Double тощо. Це більше, ніж просто перевірка синтаксису, він зберігає весь json в пам'яті. Це може бути значним для інтенсивних навантажень. Якщо існує краще рішення для перевірки синтаксису?
javapowered

15

У Google Gson ви можете використовувати JsonParser:

import com.google.gson.JsonParser;

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

3
Зауважте, що це не призводить до помилок у некрученому рядку ala "asdf"
Ендрю

1
Він також не відкидає проміжні коми в масивах JSON.
Сотіріос Деліманоліс

Я не можу дуже сподіватися на це ... там сказано, що рядок "Зберегти" піддається аналізу.
Дерік

Врахуйте , що приклад gson тут використовується щадний режим синтаксичного аналізу , який все ще дозволяє багато відхилень. Дивіться більше деталей із тестовою скринькою та прикладом суворого розбору в інших моїх відповідях.
Вадим

14

Ви можете використовувати .mayBeJSON (String str), доступний у бібліотеці JSONUtils .


так ... це працює. Спасибі npinti. я намагався з gson, але такого методу я не бачив.
sappu

@sappu: Якщо ця відповідь вирішила ваше запитання, позначте це так. Більшість бібліотек, як правило, приймають рядок і намагаються розібрати її, якщо розбір не вдасться, тобто рядок не є дійсною рядкою JSON, вона викине виняток.
npinti

@npinti: не вдалося отримати додаткові}. Повертає справжнє значення для недійсного рядка з додатковою дужкою =>}
Vivek

3
Цей метод буквально лише перевіряє, що рядок починається і закінчується цитатами або дужками. Дуже ненадійний.
Майкл Мансі

2
тому назва методу "можливо", а не "є" :)
Хоа,

5

Це залежить від того, що ви намагаєтесь довести своєю валідацією. Безумовно, аналіз json, як запропонували інші, є кращим, ніж використання регулярних виразів, тому що граматика json є складнішою, ніж може бути представлена ​​лише регулярними виразами.

Якщо json коли-небудь буде аналізуватися тільки вашим кодом java, тоді використовуйте той же аналізатор, щоб перевірити його.

Але просто розбір не обов'язково скаже вам, чи буде він прийнятий в інших середовищах. напр

  • багато парсери ігнорують проміжні коми в об’єкті або масиві, але старі версії IE можуть вийти з ладу, коли вони потрапляють у кінцеву кому.
  • Інші аналізатори можуть прийняти коду, що знаходиться в кінці, але додати невизначений / нульовий запис після нього.
  • Деякі аналізатори можуть дозволяти імена властивостей, які не котируються.
  • Деякі аналізатори можуть по-різному реагувати на символи, що не належать до ASCII, у рядках.

Якщо ваша перевірка повинна бути дуже ретельною, ви можете:

  • спробуйте різні парсери, поки ви не знайдете той, який не спрацьовує у всіх кутових випадках, про які я згадував вище
  • або ви, ймовірно, можете запустити jsonlint, використовуючи javax.script. *,
  • або комбінувати за допомогою аналізатора із запуском jshint за допомогою javax.script. *.

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

Завантажте бібліотеку stringtree-json


Чи можна визначити рядок як вище? Або просто для Ідеї.
Сантрон Манібхараті

не можливо, це було пов’язано з моєю
помилкою. тепер

1
JSONValidatingReader не є частиною Java API
IgorGanapolsky

Будь ласка, використовуйте вищезгадану бібліотеку, спасибі
Jamsheer

2

Трохи про розбір:

Json, і фактично всі мови, використовують граматику, яка є набором правил, які можуть бути використані в якості заміни. щоб проаналізувати json, потрібно в основному опрацювати ці заміни в зворотному порядку

Json - це контекстна граматика , що означає, що ви можете мати нескінченно вкладені об'єкти / масиви, і json все ще буде дійсним. Регекс обробляє лише звичайні граматики (звідси 'reg' у назві), що є підмножиною без контекстних граматик, які не дозволяють нескінченно вкладати, тому неможливо використовувати лише регулярний вираз для розбору всіх дійсних json. Ви можете використовувати складний набір регулярних виразів та циклів з припущенням, що ніхто не вкладеться в минуле, скажімо, на 100 рівнів глибиною, але все одно це буде дуже важко.

якщо ви готові написати власний аналізатор,
ви можете зробити рекурсивний аналізатор спуску після відпрацювання граматики


2

Перевірте, чи вказана рядок є JSON у Котліні . Я перетворив відповідь MByD Java на Котлін

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

1

Тут ви можете знайти інструмент, який може перевірити файл JSON, або ви можете просто дезаріалізувати свій файл JSON будь-якою бібліотекою JSON, і якщо операція пройде успішно, вона повинна бути дійсною (наприклад, google-json, яка видасть виняток, якщо введення синтаксичний аналіз не є дійсним JSON).


1

Використовуючи Playframework 2.6, бібліотеку Json, знайдену в java api, також можна використовувати для простого розбору рядка. Рядок може бути або елементом json масиву json. Оскільки повернене значення не має важливого значення, ми просто вловимо помилку розбору, щоб визначити, що рядок є правильним рядком json чи ні.

    import play.libs.Json;

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

1

IMHO, найелегантніший спосіб - це використання API Java для обробки JSON (JSON-P), одного з стандартів JavaEE, який відповідає 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();
}

Використовуючи Maven, додайте залежність від JSON-P:

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

Для отримання додаткової інформації відвідайте офіційну сторінку JSON-P .


1

Ось робочий приклад для суворого розбору json з бібліотекою gson :

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

Дивіться також мою іншу детальну відповідь у розділі Як перевірити, чи дійсний JSON на Java, використовуючи GSON з додатковою інформацією та розширеним тестовим випадком з різними недійсними прикладами.


1

Як бачите, рішень дуже багато, вони в основному розбирають JSON, щоб перевірити його, і в кінці вам доведеться розібратися, щоб переконатися.

Але, залежно від контексту, ви можете покращити вистави за допомогою попередньої перевірки.

Те, що я роблю, коли я викликаю API, - це просто перевірити, що перший символ "{", а останній - "}". Якщо це не так, я не можу створювати аналізатор.


0

Я знайшов для цього дуже просте рішення.

Спочатку встановіть цю бібліотеку net.sf.json-libдля неї.

    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
    }

Зроблено. Насолоджуйтесь


0

Відповіді частково правильні. Я також зіткнувся з тією ж проблемою. Розбір json і перевірка виключення здається звичайним способом, але рішення не вдається для вхідного json щось подібне

{"outputValueSchemaFormat": "", "sortByIndexInRecord": 0, "sortOrder": 847874874387209 "спадний"} kajhfsadkjh

Як ви бачите, json недійсний, оскільки існують символи сміття. Але якщо ви спробуєте проаналізувати вищевказаний json за допомогою jackson або gson, ви отримаєте проаналізовану карту дійсного символу json та сміття, яке не враховується. Що не є необхідним рішенням, коли ви використовуєте аналізатор для перевірки дійсності json.

Для вирішення цієї проблеми дивіться тут .

PS: На це запитання я поставив і відповів.


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

а потім зателефонуйте, щоб ця функція пройшла у вашій строці 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.");
        }
    }
}

Вищевказане рішення охоплює обидва сценарії:

  • дублікат ключа
  • невідповідні лапки або відсутні дужки тощо

0

Рішення за допомогою javax.jsonбібліотеки:

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

Ви можете використовувати WellFormedJsonклас з Валідол бібліотеки декларативною перевірки.

Сама декларація може виглядати наступним чином:

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

Фаза перевірки виглядає так:

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

Це може здатися зайвим для такого простого завдання, але воно світиться, коли вам доведеться перевірити складний запит. Перегляньте розділ швидкого запуску validol .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.