14
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

[Embulk] Built-in JSON Parser plugin の新機能のご紹介

TL;DR

2019/03/11 (JST) にリリースされたEmbulk 0.9.16から、組み込みのJSON parser pluginにいくつかの新機能が正式に追加されました。

これにより、Filter pluginや、既存のOSS JSON parser pluginであるembulk-parser-jsonpath, embulk-parser-jsonl で行っていたいくつかの処理を組み込みのプラグインだけで実施できるようになりました。それらの新機能や既存のOSSのプラグインとの違いを解説します。

(おさらい) 既存のJSON parser pluginの挙動

複数のJSON objectを入力として、1オブジェクトをEmbulkにおけるJSON型1カラムを持つレコードとして読み込みます。

{"id": 1, "name": "Alice"}
{"id": 2, "name": "Bob"}
in:
  type: ...
  parser:
    type: json
+-------------------------+
|             record:json |
+-------------------------+
| {"id":1,"name":"Alice"} |
|   {"id":2,"name":"Bob"} |
+-------------------------+

JSON pointer to root

root を指定することで、JSON Pointer の形式で各JSON object内で読み取るレコードのRootを指定することができるようになりました。

{"user": {"id": 1, "name": "Alice"}}
{"user": {"id": 2, "name": "Bob"}}
in:
  type: ...
  parser:
    type: json
    root: /user

+-------------------------+
|             record:json |
+-------------------------+
| {"id":1,"name":"Alice"} |
|   {"id":2,"name":"Bob"} |
+-------------------------+

任意のキーをカラムとして指定する

各JSONオブジェクト内の任意のキーをEmbulkのカラムとして指定できるようになりました。

{"id": 1, "name": "Alice"}
{"id": 2, "name": "Bob"}
in:
  type: ...
  parser:
    type: json
    columns:
      - {name: id, type: long}
      - {name: name, type: string}
+---------+-------------+
| id:long | name:string |
+---------+-------------+
|       1 |       Alice |
|       2 |         Bob |
+---------+-------------+

また、element_atを用いて、JSONオブジェクト内の任意パスをJSON Pointer形式で指定できます。このとき、Rootポインターからの相対パスを指定します。

{"id": 1, "name": "Alice", "tags": ["a", "b", "c"]}
{"id": 2, "name": "Bob", "tags": ["d", "e"]}
in:
  type: ...
  parser:
    type: json
    columns:
      - {name: id, type: long}
      - {name: name, type: string}
      - {name: first_tag, type: string, element_at: /tags/0}
+---------+-------------+------------------+
| id:long | name:string | first_tag:string |
+---------+-------------+------------------+
|       1 |       Alice |                a |
|       2 |         Bob |                d |
+---------+-------------+------------------+

Flattening JSON array

flatten_json_array オプション(デフォルトfalse)をtrueに設定することで、JSON arrayを複数のEmbulkレコードとして展開することができます。

[
  {"id": 1, "name": "Alice"},
  {"id": 2, "name": "Bob"}
]
in:
  type: ...
  parser:
    type: json
    flatten_json_array: true
+-------------------------+
|             record:json |
+-------------------------+
| {"id":1,"name":"Alice"} |
|   {"id":2,"name":"Bob"} |
+-------------------------+

これは、 rootと併用し、以下のようにJSONオブジェクト内の配列を展開する事もできます。

{
  "results": [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"}
  ]
}
in:
  type: ...
  parser:
    type: json
    flatten_json_array: true
    root: /results
+-------------------------+
|             record:json |
+-------------------------+
| {"id":1,"name":"Alice"} |
|   {"id":2,"name":"Bob"} |
+-------------------------+

既存のOSS JSON parser pluginとの違い

これらのプラグインの基本的な機能は同等のことができるようになっているので、未対応の機能を使ってない場合はbuilt-inのプラグインに移行可能です。

embulk-parser-jsonl

  • columnsオプションによるカラムを指定は同じ事ができるようになりました。
  • default_typecastオプションによる型の自動変換は対応していません。1

embulk-parser-jsonpath

  • root オプションによる展開元の指定は rootflatten_json_array で同等の事ができるようになりました。
  • path オプションによる値のJSONPathによる指定は、JSON Pointerで同等のことができるようになりました。
  • ただし、JSON PointerはJSONPathほど複雑なことができる訳では無いので、単に値をポイントする以上のことをJSONPathで行っている場合は引き続きこちらのParserが必要になります。2
  • 1, yes, on などの文字列のboolean型への型変換は対応していません。

  1. 型変換に関してはParserではなく、Filterで対応するべきという方針から公式では非対応としています。 

  2. JSONPathはRFCで定義された仕様がなく挙動がライブラリによってまちまちな背景から、手堅いJSON Pointerを採用しています。また、Embulkが依存しているJacksonがJSON Pointerをサポートしていることも理由のひとつです。 

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
14
Help us understand the problem. What are the problem?