このライブラリは現在メンテナンス モードにあり、erosb/json-sKema に置き換えられます。
このリポジトリには新しい機能はありません。 JSON スキーマ仕様のドラフト 04、ドラフト 06、およびドラフト 07 バージョンに対する確実なサポートを提供します。
最新のドラフト 2020-12 は、erosb/json-sKema でのみサポートされています。
このプロジェクトは、JSON スキーマ ドラフト v4、ドラフト v6、およびドラフト v7 仕様の実装です。 JSON データを表すために org.json API (Douglas Crockford によって作成) を使用します。
JSON スキーマとは何かをすでに知っており、それを Java アプリケーションで利用して JSON データを検証したいと仮定します。ただし、すでにお気づきかもしれませんが、JSON スキーマ仕様の別の Java 実装もあります。したがって、どれを使用するかについてのアドバイスをいくつか示します。
次の依存関係をpom.xml
に追加します。
< dependency >
< groupId >com.github.erosb</ groupId >
< artifactId >everit-json-schema</ artifactId >
< version >1.14.4</ version >
</ dependency >
古いバージョンに関する注意: 1.6.0
から1.9.1
までのバージョンはcom.github.everit-org.json-schema:org.everit.json.schema
座標を持つ JitPack でのみ見つかります。バージョン1.0.0
... 1.5.1
は、Maven Central のorg.everit.json:org.everit.json.schema
座標で入手できます。
このライブラリを Java 6/7 で動作させる試みがいくつかありました。
バージョン 1.9.2 の Java6 ポートは @mindbender1 によって開発され、次の座標を使用して Maven Central からアクセスできます。
< dependency >
< groupId >com.github.erosb</ groupId >
< artifactId >everit-json-schema-jdk6</ artifactId >
< version >1.9.2</ version >
</ dependency >
古いバージョンのバックポート:
com.doctusoft:json-schema-java7:1.4.1
でした。com.github.rdruilhe.json-schema:org.everit.json.schema:1.1.1
として入手可能です。 import org . everit . json . schema . Schema ;
import org . everit . json . schema . loader . SchemaLoader ;
import org . json . JSONObject ;
import org . json . JSONTokener ;
// ...
try ( InputStream inputStream = getClass (). getResourceAsStream ( "/path/to/your/schema.json" )) {
JSONObject rawSchema = new JSONObject ( new JSONTokener ( inputStream ));
Schema schema = SchemaLoader . load ( rawSchema );
schema . validate ( new JSONObject ( "{ " hello " : " world " }" )); // throws a ValidationException if this object is invalid
}
JSON スキーマには現在、Draft 3、Draft 4、Draft 6、および Draft 7 の 4 つのメジャー リリースがあります。このライブラリは 3 つの新しいリリースを実装しています。違いについては、こことここで簡単に確認できます。 2 つのバージョンには多くの違いがあり、ドラフト 6 にはドラフト 4 との下位互換性がないため、どちらのバージョンを使用するかを知っておくとよいでしょう。
使用する JSON スキーマのバージョンを示す最良の方法は、 "$schema"
キーを使用してドキュメント ルートにそのメタスキーマ URL を含めることです。これは一般的な表記法であり、ライブラリによってどのバージョンを使用するかを決定しやすくなります。
クイックリファレンス:
"$schema": "http://json-schema.org/draft-04/schema"
がある場合、Draft 4 が使用されます。"$schema": "http://json-schema.org/draft-06/schema"
がある場合、Draft 6 が使用されます。"$schema": "http://json-schema.org/draft-07/schema"
がある場合、Draft 7 が使用されます。メタスキーマのバージョンを明示的に指定する場合は、次のようにローダーを構成することで、デフォルトをドラフト 4 からドラフト 6 / 7 に変更できます。
SchemaLoader loader = SchemaLoader . builder ()
. schemaJson ( yourSchemaJSON )
. draftV6Support () // or draftV7Support()
. build ();
Schema schema = loader . load (). build ();
バージョン1.1.0
以降、バリデーターは (最初のスキーマ違反ですぐに失敗するのではなく) すべてのスキーマ違反を収集します。それぞれの失敗は、ドキュメントのルートから違反部分を指す JSON ポインターによって示されます。複数のスキーマ違反が検出された場合は、違反の最も一般的な親要素でValidationException
がスローされ、 ValidationException#getCausingExceptions()
メソッドを使用して個別の違反を取得できます。
上記の概念を説明するために、例を見てみましょう。次のスキーマを考えてみましょう。
{
"type" : " object " ,
"properties" : {
"rectangle" : { "$ref" : " #/definitions/Rectangle " }
},
"definitions" : {
"size" : {
"type" : " number " ,
"minimum" : 0
},
"Rectangle" : {
"type" : " object " ,
"properties" : {
"a" : { "$ref" : " #/definitions/size " },
"b" : { "$ref" : " #/definitions/size " }
}
}
}
}
次の JSON ドキュメントには、スキーマに対する違反が 1 つだけあります (「a」を負にすることはできないため)。
{
"rectangle" : {
"a" : -5 ,
"b" : 5
}
}
この場合、スローされたValidationException
は#/rectangle/a
を指し、サブ例外は含まれません。
try {
schema . validate ( rectangleSingleFailure );
} catch ( ValidationException e ) {
// prints #/rectangle/a: -5.0 is not higher or equal to 0
System . out . println ( e . getMessage ());
}
ここで、複数の違反が処理される方法を説明するために、「a」プロパティと「b」プロパティの両方が上記のスキーマに違反している次の JSON ドキュメントを考えてみましょう。
{
"rectangle" : {
"a" : -5 ,
"b" : " asd "
}
}
この場合、スローされたValidationException
は#/rectangle
を指し、 #/rectangle/a
と#/rectangle/b
を指す 2 つのサブ例外があります。
try {
schema . validate ( rectangleMultipleFailures );
} catch ( ValidationException e ) {
System . out . println ( e . getMessage ());
e . getCausingExceptions (). stream ()
. map ( ValidationException :: getMessage )
. forEach ( System . out :: println );
}
これにより、次の出力が表示されます。
#/rectangle: 2 schema violations found
#/rectangle/a: -5.0 is not higher or equal to 0
#/rectangle/b: expected type: Number, found: String
バージョン1.4.0
以降、 ValidationException
インスタンスを JSON 形式の失敗レポートとして出力できるようになりました。 ValidationException#toJSON()
メソッドは、次のキーを持つJSONObject
インスタンスを返します。
"message"
: プログラマ向けの例外メッセージ (検証失敗の説明)"keyword"
: 違反した JSON スキーマのキーワード"pointerToViolation"
: 入力ドキュメントのルートから検証失敗の原因となったそのフラグメントまでのパスを示す JSON ポインター"schemaLocation"
: スキーマ JSON ルートから違反キーワードまでのパスを示す JSON ポインター"causingExceptions"
: サブ例外の (空の可能性がある) 配列。各サブ例外は、このリストで説明されているのと同じ構造を持つ JSON オブジェクトとして表されます。例外の発生については、上記を参照してください。完全な障害レポートは階層ツリー構造であることを考慮してください。原因のサブ原因は#getCausingExceptions()
を使用して取得できます。
ValidationListener
は、インスタンス JSON がスキーマとどのように一致するか (または一致しないか) についてのあいまいさを解決する目的を果たします。 ValidationListener
実装をバリデーターにアタッチして、中間の成功/失敗結果に関するイベント通知を受け取ることができます。
例:
import org . everit . json . schema . Validator ;
...
Validator validator = Validator . builder ()
. withListener ( new YourValidationListenerImplementation ())
. build ();
validator . performValidation ( schema , input );
現在サポートされているイベント:
"$ref"
参照が解決されています"allOf"
/ "anyOf"
/ "oneOf"
スキーマに一致するサブスキーマ"allOf"
/ "anyOf"
/ "oneOf"
スキーマの下のサブスキーマが一致しません"if"
スキーマの一致"if"
スキーマが一致しません"then"
スキーマの一致"then"
スキーマが一致しません"else"
スキーマの一致"else"
スキーマが一致しません詳細については、 org.everit.json.schema.event.ValidationListener
インターフェースの javadoc を参照してください。特定のイベント クラスには適切な#toJSON()
および#toString()
実装もあるので、簡単に解析可能な形式で出力できます。
デフォルトでは、検証エラーは収集モードでレポートされます (「失敗の調査」の章を参照)。これは詳細なエラー レポートを得るのに便利ですが、状況によっては、失敗が見つかった場合に JSON ドキュメントの残りの部分をチェックせずに検証を停止する方が適切です。この高速失敗検証モードを切り替えるには
Schema#validate(input)
を呼び出す代わりに、スキーマのValidator
インスタンスを明示的に構築する必要があります。ValidatorBuilder
のfailEarly()
メソッドを呼び出す必要があります。例:
import org . everit . json . schema . Validator ;
...
Validator validator = Validator . builder ()
. failEarly ()
. build ();
validator . performValidation ( schema , input );
注: Validator
クラスは不変でスレッドセーフであるため、検証ごとに新しいクラスを作成する必要はなく、一度設定するだけで十分です。
場合によっては、数値またはブール値を検証するときに、解析可能な文字列値をそのようなプリミティブとして受け入れることが合理的です。これは、後続の処理でもこれらのリテラルが適切な数値および論理値に自動的に解析されるためです。また、文字列以外のプリミティブ値は文字列に変換するのが簡単なので、json プリミティブを文字列として許可しないのはなぜでしょうか。
たとえば、次のスキーマを考えてみましょう。
{
"properties" : {
"booleanProp" : {
"type" : " boolean "
},
"integerProp" : {
"type" : " integer "
},
"nullProp" : {
"type" : " null "
},
"numberProp" : {
"type" : " number "
},
"stringProp" : {
"type" : " string "
}
}
}
次の JSON ドキュメントは検証に失敗しますが、すべての文字列は適切な値に簡単に変換できます。
{
"numberProp" : " 12.34 " ,
"integerProp" : " 12 " ,
"booleanProp" : " true " ,
"nullProp" : " null " ,
"stringProp" : 12.34
}
この場合、上記のインスタンスがスキーマに対する検証に合格するようにするには、寛大なプリミティブ検証構成をオンにして使用する必要があります。例:
import org . everit . json . schema .*;
...
Validator validator = Validator . builder ()
. primitiveValidationStrategry ( PrimitiveValidationStrategy . LENIENT )
. build ();
validator . performValidation ( schema , input );
注: 寛大な解析モードでは、22 個のすべてのブール値リテラルが論理値として受け入れられます。
JSON スキーマ仕様では、デフォルト値を示すための「default」キーワードが定義されていますが、それが検証プロセスにどのように影響するかについては明示的には述べられていません。デフォルトでは、このライブラリはデフォルト値を設定しませんが、この機能が必要な場合は、スキーマをロードする前にSchemaLoaderBuilder#useDefaults(boolean)
メソッドによって有効にすることができます。
{
"properties" : {
"prop" : {
"type" : " number " ,
"default" : 1
}
}
}
JSONObject input = new JSONObject ( "{}" );
System . out . println ( input . get ( "prop" )); // prints null
Schema schema = SchemaLoader . builder ()
. useDefaults ( true )
. schemaJson ( rawSchema )
. build ()
. load (). build ();
schema . validate ( input );
System . out . println ( input . get ( "prop" )); // prints 1
スキーマに"default"
値を持つプロパティがinput
から欠落している場合、それらは検証中にバリデーターによって設定されます。
JSON スキーマの"regex"
キーワードをサポートするために、ライブラリでは 2 つの可能な実装が提供されています。
java.util.regex
パッケージに基づいていますRE2J ライブラリはjava.util.regex
よりも大幅に優れたパフォーマンスを提供しますが、 java.util
または ECMA 262 でサポートされる構文と完全な互換性はありません。そのため、パフォーマンスが気になり、その制限が許容できる場合には RE2J をお勧めします。
RE2J 実装は、 SchemaLoaderBuilder#regexpFactory()
呼び出しでアクティブ化できます。
SchemaLoader loader = SchemaLoader . builder ()
. regexpFactory ( new RE2JRegexpFactory ())
// ...
. build ();
注:
pom.xml
で RE2J 実装を除外することをお勧めします。java.util
実装が使用され、1.8.0 では RE2J 実装が使用され、いくつかのリグレッションが報告されたため、1.9.0 では構成可能になりました。 このライブラリは、ドラフト 7 で初めて登場したreadOnly
およびwriteOnly
キーワードをサポートします。この機能を利用したい場合は、検証の前に、検証が読み取りコンテキストで行われるか書き込みコンテキストで行われるかをバリデーターに伝える必要があります。例:
スキーマ.json:
{
"properties" : {
"id" : {
"type" : " number " ,
"readOnly" : true
}
}
}
検証コード スニペット:
Validator validator = Validator . builder ()
. readWriteContext ( ReadWriteContext . WRITE )
. build ();
validator . performValidation ( schema , new JSONObject ( "{ " id " :42}" ));
この場合、検証がWRITE
コンテキストで行われることをバリデーターに伝え、入力 JSON オブジェクトに"id"
プロパティが表示され、スキーマで"readOnly"
としてマークされているため、この呼び出しはValidationException
をスローします。
バージョン1.2.0
以降、ライブラリは"format"
キーワード (仕様のオプション部分) をサポートします。
サポートされる形式は、使用するスキーマ仕様のバージョンによって異なります (標準形式が検証仕様のさまざまなバージョンで導入されているため)。
サポートされている標準形式の互換性表は次のとおりです。
ドラフト 4 | ドラフト6 | ドラフト 7 | |
---|---|---|---|
日時 | ✅ | ✅ | ✅ |
電子メール | ✅ | ✅ | ✅ |
ホスト名 | ✅ | ✅ | ✅ |
IPv4 | ✅ | ✅ | ✅ |
IPv6 | ✅ | ✅ | ✅ |
ウリ | ✅ | ✅ | ✅ |
uri参照 | ✅ | ✅ | |
uri テンプレート | ✅ | ✅ | |
json-ポインター | ✅ | ✅ | |
日付 | ✅ | ||
時間 | ✅ | ||
正規表現 | ✅ | ||
相対jsonポインター | ✅ |
このライブラリは、カスタム形式バリデータの追加もサポートしています。カスタムバリデーターを使用するには、基本的に次のことを行う必要があります
org.everit.json.schema.FormatValidator
インターフェースを実装するクラスで独自の検証を作成します。org.everit.json.schema.loader.SchemaLoader.SchemaLoaderBuilder
インスタンス内の名前にバインドします。タスクが偶数の文字数の文字列を受け入れるカスタム バリデーターを作成することであると仮定します。
カスタムFormatValidator
次のようになります。
public class EvenCharNumValidator implements FormatValidator {
@ Override
public Optional < String > validate ( final String subject ) {
if ( subject . length () % 2 == 0 ) {
return Optional . empty ();
} else {
return Optional . of ( String . format ( "the length of string [%s] is odd" , subject ));
}
}
}
EvenCharNumValidator
"format"
値 (たとえば、 "evenlength"
) にバインドするには、バリデーター インスタンスをスキーマ ローダー構成内のキーワードにバインドする必要があります。
JSONObject rawSchema = new JSONObject ( new JSONTokener ( inputStream ));
SchemaLoader schemaLoader = SchemaLoader . builder ()
. schemaJson ( rawSchema ) // rawSchema is the JSON representation of the schema utilizing the "evenlength" non-standard format
. addFormatValidator ( "evenlength" , new EvenCharNumValidator ()) // the EvenCharNumValidator gets bound to the "evenlength" keyword
. build ();
Schema schema = schemaLoader . load (). build (); // the schema is created using the above created configuration
schema . validate ( jsonDocument ); // the document validation happens here
JSON スキーマ ドキュメントでは、相対 URI を使用して以前に定義された型を参照できます。このような参照は"$ref"
および"$id"
キーワードを使用して表現されます。この仕様では、解決スコープの変更と参照解除について詳しく説明していますが、最初に出現する"$ref"
または"$id"
が相対 URI である場合に予期される動作については説明されていません。
この実装の場合、適切なビルダー メソッドを使用して、ベース URI (解決スコープ) として機能する絶対 URI を明示的に定義できます。
SchemaLoader schemaLoader = SchemaLoader . builder ()
. schemaJson ( jsonSchema )
. resolutionScope ( "http://example.org/" ) // setting the default resolution scope
. build ();
スキーマが大きくなるにつれて、スキーマを複数のソース ファイルに分割し、それらを"$ref"
参照で結び付けたくなるでしょう。スキーマを (HTTP 経由で提供するのではなく) クラスパスに保存したい場合、推奨される方法は、 classpath:
プロトコルを使用してスキーマを相互参照させることです。 classpath:
プロトコルを機能させるには:
SchemaClient
を利用できます。例: SchemaLoader schemaLoader = SchemaLoader . builder ()
. schemaClient ( SchemaClient . classPathAwareClient ())
. schemaJson ( jsonSchema )
. resolutionScope ( "classpath://my/schemas/directory/" ) // setting the default resolution scope
. build ();
この構成を考慮すると、次の参照はjsonSchema
で適切に解決されます。
{
"properties" : {
"sameDir" : { "$ref" : " sameDirSchema.json " },
"absPath" : { "$ref" : " classpath://somewhere/else/otherschema.json " },
"httpPath" : { "$ref" : " http://example.org/http-works-as-usual " },
}
}
そして、 sameDirSchema.json
クラスパス上の/my/schemas/directory/sameDirSchema.json
で検索されます。
場合によっては、URL を通じてスキーマをロードする代わりに、任意の URI (おそらく uuid) を割り当てる、プリロードされたスキーマを操作すると便利です。これは、スキーマ ローダーの#registerSchemaByURI()
メソッドを使用してスキーマを URI に割り当てることで実行できます。例:
SchemaLoader schemaLoader = SchemaLoader . builder ()
. registerSchemaByURI ( new URI ( "urn:uuid:a773c7a2-1a13-4f6a-a70d-694befe0ce63" ), aJSONObject )
. registerSchemaByURI ( new URI ( "http://example.org" ), otherJSONObject )
. schemaJson ( jsonSchema )
. resolutionScope ( "classpath://my/schemas/directory/" )
. build ();
注:
JSONObject
またはBoolean
である必要があります (これら 2 つは他に共通のスーパークラスを持たないため、正式なパラメーターの型はObject
のみです)。SchemaClient
実装を定義することもできます。また、 java.net
パッケージの拡張可能なプロトコル処理を利用することもできます)。 依存関係の一部はライブラリから除外できますが、いくつかの制限はありますが、引き続き使用できます。
com.damnhandy:handy-uri-templates
依存関係を除外する場合、スキーマでは"uri-template"
形式を使用しないでください。commons-validator:commons-validator
依存関係を除外する場合、スキーマでは次の形式を使用しないでください: "email"
、 "ipv4"
、 "ipv6"
、 "hostname"
ライブラリのバージョン別:
バージョン 1.0.0 ~ 1.5.1 で生成された javadoc は、javadoc.io で入手できます。
その間のバージョン (1.6.0 ~ 1.9.1) については、どこにも公開されていません。