指定された文字列がJavaで有効なJSONかどうかを確認する方法


155

JavaでJSON文字列を検証するにはどうすればよいですか?または、正規表現を使用して解析できますか?


gsonで解析してみますか?正規表現による検証は良い考えではないかもしれません
aishwarya '16 / 04/12

2
json.orgには、非常に多くのパーサーへのリンクがあります
MartinK 2012

回答:


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

このコードは、githubmaven、および部分的にAndroid 利用可能なorg.json JSON API実装を使用ます。


2
近いですが、JSONArrayの検証がありません(この投稿をより適切な関数で更新しました)
Arthur

9
「{'hello': 'foo'} 'invalid'」のようなjson文字列を試しました({}の外に 'invalid'が追加されました)。JSONObjectがParseExceptionをスローしていません。私はorg.json.JSONObjectを使用しています。これは予想されますか?
林宗一

16
JSONObjectが含まれているライブラリについては言及しませんでしたが、標準のJava libでは見ていませんでした
KrzysztofKrasoń

6
このソリューションはほとんどの場合に機能しますが、特定の状況では失敗する可能性があります。たとえば、実際には構文エラーである右中括弧の直前にカンマを付けることができます。その他のまれなケースについては、json.org / javadoc / org / json / JSONObject.htmlを参照してください。
Hua2308 2015

9
なぜポスターにコードスニペット付きのインポートステートメントを含める必要がないのか理解できません。ここで重要です。ここで2番目に評価された答えははるかに優れています。
seansand 2017

100

ジャクソン図書館

1つのオプションは、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は、RFC-4627に
eurythmia

@eurythmia True!バージョン3.0では、問題
JeanValjean

1
これは{key:value}も検証しますが、有効なjsonではありません
Pratapi Hemant Patel

2
ジャクソンの落とし穴:new ObjectMapper().readTree("28xjRBuOQqupRopHeSuhRQ")IntNode(28)として例外なしで解析します。あまり期待されていません...
mgaert 2018年

1
私が理解しているように、このソリューションはjson全体を検証するだけでなく、解析(および保存)します。数値を整数/ロング/ダブルなどに変換します。これは単なる構文チェックではなく、json全体をメモリに格納します。これは、負荷が大きい場合に重要になることがあります。構文チェックのためのより良い解決策が存在する場合?
javapowered 2018

15

GoogleのGsonあなたはJsonParserを使用することができます。

import com.google.gson.JsonParser;

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

3
これは括弧なしの文字列ala "asdf"でエラーをスローしないことに注意してください
Andrew

1
また、JSON配列の末尾のコンマも拒否しません。
Sotirios Delimanolis 2016年

私はそれを本当に信頼することはできません...文字列「Save」は解析可能であると言っています。
Dherik 2017年

ここでのgsonの例は、多くの偏差を許容する寛大な解析モードを使用することに注意してください。テストケース厳密な解析の例を使用して詳細を他の回答で参照してください
Vadzim

14

あなたは使用することができ.mayBeJSON(文字列strが)で利用可能JSONUtilsのライブラリ。


はい...これは機能しています npinti、ありがとう。私はgsonで試していましたが、そのような方法は見たことはありません。
sappu

@sappu:この回答で問題が解決した場合は、マークしてください。ほとんどのライブラリは文字列を取り込んで解析しようとする傾向があり、解析が失敗した場合、つまり文字列が有効なJSON文字列でない場合は、例外がスローされます。
npinti

@npinti:余分な}のために失敗しました。余分なブラケットがある無効な文字列に対してtrueを返します=>}
Vivek

3
このメソッドは、文字列の開始と終了が引用符または角かっこであるかどうかを文字どおりチェックするだけです。非常に信頼できません。
Michael Munsey

2
そのため、メソッド名は「is」ではなく「maybe」です:)
Khoa

5

これは、検証で何を証明しようとしているのかによって異なります。確かに、他の人が示唆しているようにjsonを解析する方が、正規表現を使用するよりも優れています。なぜなら、jsonの文法は、正規表現だけで表現できるよりも複雑だからです。

jsonがJavaコードによってのみ解析される場合は、同じパーサーを使用してそれを検証します。

しかし、解析だけでは、他の環境で受け入れられるかどうかは必ずしもわかりません。例えば

  • 多くのパーサーはオブジェクトまたは配列の末尾のコンマを無視しますが、古いバージョンのIEは末尾のコンマにヒットすると失敗する可能性があります。
  • 他のパーサーは末尾のコンマを受け入れますが、その後に未定義/ nullエントリを追加します。
  • 一部のパーサーは、引用符で囲まれていないプロパティ名を許可する場合があります。
  • 一部のパーサーは、文字列内の非ASCII文字に対して異なる反応をする場合があります。

検証を徹底的に行う必要がある場合は、次のことができます。


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ライブラリをダウンロードしてください


上記のように文字列を定義することは可能ですか?またはそれはアイデアのためだけです。
Santron Manibharathi、2014

不可能、それは私の
間違い

1
JSONValidatingReaderはJava APIの一部ではありません
IgorGanapolsky 2017

上記のライブラリを使用してください、ありがとう
Jamsheer 2017年

2

解析について少し:

Json、そして実際にはすべての言語は、置換として使用できる一連のルールである文法を使用します。jsonを解析するには、基本的にこれらの置換を逆に行う必要があります

jsonはコンテキストフリーの文法です。つまり、オブジェクト/配列を無限にネストしても、jsonは引き続き有効です。正規表現は通常の文法のみを処理します(したがって、名前の「reg」)。これは、無限のネストを許可しないコンテキストフリーの文法のサブセットであるため、正規表現のみを使用してすべての有効なjsonを解析することはできません。100レベルの深さで誰も入れ子にならないという前提で、複雑な正規表現とループのセットを使用できますが、それでも非常に困難です。

独自のパーサーを作成する準備
ができている場合は、文法を学習した後に再帰降下パーサーを作成できます


2

指定された文字列がKotlinで有効なJSONかどうかを確認します。MByD Javaの回答をKotlin に変換しました

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を使用すると、Java APIにあるJsonライブラリを使用して、文字列を単純に解析することもできます。文字列は、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、最もエレガントな方法は、JSON 374に準拠するJavaEE標準の1つである、JSON処理用Java API(JSON-P)を使用することです。

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を解析してチェックし、最後に確実に解析する必要があります。

ただし、コンテキストによっては、事前チェックでパフォーマンスを向上させることができます。

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 "descending"} 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

Validol宣言型検証ライブラリの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のクイックスタートセクションをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.