LoginSignup
0
0

More than 1 year has passed since last update.

Amazon S3 SelectでJSON要素マッチしないクエリの出力

Posted at

概要

Amazon S3 SelectでJSONデータをクエリした際に指定要素が無い場合の挙動で少しハマったのでメモしておきます。

現象再現

ソースデータ

下記のようなJSONテキストファイルを準備します。
1つ目のオブジェクトは attr.age要素あり、2つ目のオブジェクトはありません。

source.json
{
  "id": 101,
  "name": "taro",
  "attr": {
    "region": "Japan",
    "age": 30
  }
}
{
  "id": 102,
  "name": "hanako",
  "attr": {
    "region": "United States"
  }
}

S3へアップロード

$ aws s3 cp source.json  s3://my-bucket/

S3 Select

ソースはJSON、出力はCSVとします。
出力CSVはすべての行について下記の4列となることを期待しています

列位置 想定出力列名 JSON上の表記
1 id id
2 name name
3 age attr.age
4 region attr.region
$ aws s3api select-object-content --bucket my-bucket --key source.json \
--expression-type SQL \
--expression "SELECT s.id, s.name, s.attr.age, s.attr.region FROM s3object s" \
--input-serialization '{"JSON": {"Type": "LINES"}}' \
--output-serialization '{"CSV": {}}' \
outfile.csv

出力を確認

1行目は期待通りですが、2行目がNGです。3列目 age 列が抜けています。
確かにソースJSONには attr.age要素が無いのですが、これだと列数が不一致になってしまいます。

$ cat outfile.csv
101,taro,30,Japan
102,hanako,United States

考察

出力をJSONにすると age 要素なしで出力されます。JSONとしてはこれで正しいですね。
ただ、CSVの場合は行ごとに列の数が一致しないのは多くの場合期待されないと思います。

$ aws s3api select-object-content --bucket my-bucket --key source.json \
--expression-type SQL \
--expression "SELECT s.id, s.name, s.attr.age, s.attr.region FROM s3object s" \
--input-serialization '{"JSON": {"Type": "LINES"}}' \
--output-serialization '{"JSON": {}}' \
outfile.json

$ cat outfile.json
{"id":101,"name":"taro","age":30,"region":"Japan"}
{"id":102,"name":"hanako","region":"United States"}

対応方法

SQL関数 COALESCE を使用し、null出力を明示します。
これで値なしの列も出力されます。
(処理として適切な値があればnullではなくても良いと思います。たとえば 「999=年齢不明を示す仕様」の場合は999が良いかもしれません)

$ aws s3api select-object-content --bucket my-bucket --key source.json \
--expression-type SQL \
--expression "SELECT s.id, s.name, COALESCE(s.attr.age, null) age, s.attr.region FROM s3object s" \
--input-serialization '{"JSON": {"Type": "LINES"}}' \
--output-serialization '{"CSV": {}}' \
outfile.csv

$ cat outfile.csv
101,taro,30,Japan
102,hanako,,United States

参考:JSON出力時

JSON出力にした場合も要素数が一致するようになります。

$ aws s3api select-object-content --bucket my-bucket --key source.json \
--expression-type SQL \
--expression "SELECT s.id, s.name, COALESCE(s.attr.age, null) age, s.attr.region FROM s3object s" \
--input-serialization '{"JSON": {"Type": "LINES"}}' \
--output-serialization '{"JSON": {}}' \
outfile.json

$ cat outfile.json
{"id":101,"name":"taro","age":30,"region":"Japan"}
{"id":102,"name":"hanako","age":null,"region":"United States"}

参照ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0