JSON Pointer (RFC 6901) まとめ


JSON Pointer とは

JSON Pointer は、Jsonドキュメント内の特定の値へのパスを定義する文字列構文です。

www.rfc-editor.org

大まかに言えば、ルートからのプロパティを / で連結してパスを構築します。

以下の Jsonドキュメントが有った場合、

{
  "name": "some product",
  "price": 10.5,
  "features": [
    "easy to use",
    {
      "name": "environment friendly",
      "url": "http://example.com"
    }
  ],
  "k\"l": 6,
  "a/b": "a"
}

/name と指定すれば some product を指し示します。

主に、JSON Patch(RFC 6902) での変更ポイントを指定するために使われます。


JSON Pointer の構文

JSON Pointer は常に / から始まり、ルートからの絶対パスを指定します。

JSON Pointer として空文字を指定した場合には、対象のJSONドキュメント全体を指します。

JSON Pointer の ABNF シンタックスは以下のようになっています。

json-pointer    = *( "/" reference-token )
reference-token = *( unescaped / escaped )
unescaped       = %x00-2E / %x30-7D / %x7F-10FFFF
   ; %x2F ('/') and %x7E ('~') are excluded from 'unescaped'
escaped         = "~" ( "0" / "1" )
  ; representing '~' and '/', respectively

JSON Pointer が存在しない要素を指す場合にはエラーと評価されます。


JSON Pointer のエスケープ

プロパティ名に ~ が含まれている場合、~0 のようにエスケープし、プロパティ名に / が含まれている場合、~1 のようにエスケープする必要があります。

よって、上記 JSON ドキュメントの最後の要素は、 JSON Pointer では /a~1b と表します。 なお、~01 のデコードは ~1 であり、/ ではありません。

文字列のエスケープは通常のJSONと同様に、"(%x22), \(%x5C), 及び %x00-1F の制御コードはバックスラッシュでエスケープとなります。 上記 JSON ドキュメントでは、k\"l というJSON Pointer で 6 を指します。

また、URIフラグメント識別子の表現も許可されています(フラグメントルールで許可されていない文字はパーセントエンコード)。 上記 JSON ドキュメントでは、#/k%22l という JSON Pointer で 6 を指します。 http://example.com/schema.json#/k%22l のようにアクセスすることになります。


JSON 配列の指定

参照先がJSON配列の場合には、配列要素をゼロベースのインデックスで指定します。

前述のJSONオブジェクトを例にすれば以下のようになります。

  • /features/0 easy to use
  • /features/1/url http://example.com

/features/- と指定した場合には、配列の最後の要素の後ろを指定します。 これは主に、JSON Patch で要素を追加する場合に使用します。

配列インデックスの ABNF構文は以下のようになっています。

array-index = %x30 / ( %x31-39 *(%x30-39) )
  ; "0", or digits without a leading "0"


Relative JSON Pointer

RFC として定義されてはいませんが、絶対パスで指定する JSON Pointer に対して、相対パスを指定する Relative JSON Pointer もあります。

Relative JSON Pointer の ABNF シンタックスは以下のようになっています。

relative-json-pointer =  non-negative-integer <json-pointer>
relative-json-pointer =/ non-negative-integer "#"
non-negative-integer      =  %x30 / %x31-39 *( %x30-39 )
  ; "0", or digits without a leading "0"

Relative JSON Pointer では現在の位置を 0 で指定し、1 で1つ上の親、2 で2つ上の親を指定します。 親の指定以降は、JSON Pointer と同じ書式で、要素を下っていきます。

Relative JSON Pointer では # で、現在の位置のプロパティ名、配列の場合にはインデックスを表します。

前述と同様の、以下のJSONドキュメントにて、

{
  "name": "some product",
  "price": 10.5,
  "features": [
    "easy to use",
    {
      "name": "environment friendly",
      "url": "http://example.com"
    }
  ],
  "k\"l": 6,
  "a/b": "a"
}

現在の位置が http://example.com を指す場合(JSON Pointer における/features/1/url)、現在位置からの相対ポインタとして以下のようになります。

  • 0 -> http://example.com
  • 0# -> url
  • 1# -> 1(配列インデックス)
  • 1/name -> environment friendly
  • 2# -> features
  • 2/0 -> easy to use
  • 2/0# -> 0(配列インデックス)
  • 3 -> ドキュメント全体(ルート)