JSONにはコメント行が付けられない?ネットで見つけた方法の有用性を試してみた

110件のシェア(ちょっぴり話題の記事)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹です。AWSではJSON形式を使う機会が結構多いですよね。ただJSONを使ってて不満なことが一つあります。それはコメント行をつけることができないことです。例えばJavaScriptのようにスラッシュでコメントを表現しようとしても構文エラーとなってしまいます。

{
  "key" : "value" // コメント
}

$ cat js_test.json | jq '.'
parse error: Invalid numeric literal

特にCloudFormationのテンプレートや、IAMのポリシー設定は内容が複雑になりがちなのでコメントをつけておきたいと思うことが多々あり困っていました。

そんな時このようなブログを見つけました。「Adding Comments to JSON」。JSONでは同じキー文字列の要素が重複した場合に最後に定義したものが優先されるため、重複したキーを使ってコメントっぽく残せるのだそうです。

{
  "key" : "最初の要素はコメントとして扱うことができる",
  "key" : "value"
}

これをJSONパーサのjqに渡すとこうなります。

$ cat js_test2.json | jq '.'
{
  "key": "value"
}

なるほどこれは便利!でも本当に実用で使えるのか?AWSの各サービスで試してみました。

いろいろなツールでコメントつきJSONを試す

日本語(マルチバイト)を含める際、JSONファイルはutf-8で保存しています。

jq

上の結果からjqはうまく重複したキーを取り扱ってくれているように見えます。

CloudFormationテンプレート

AWS CloudFormation サンプルテンプレート - アジアパシフィック(東京)リージョン」で紹介されているテンプレートからサイズが一番小さい"Route53_CNAME.template"を選び、コメントをつけてから、スタックが作成できるか試してみました。

{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "AWS CloudFormation Sample Template Route53_CNAME: Sample template showing how to create an Amazon Route 53 CNAME record.  It assumes that you already have a Hosted Zone registered with Amazon Route 53. **WARNING** This template creates one or more AWS resources. You will be billed for the AWS resources used if you create a stack from this template.",

  "Parameters" : "COMMENT:パラメータを定義します",
  "Parameters" : {
    "HostedZone" : {
      "Type" : "String",
      "Description" : "The DNS name of an existing Amazon Route 53 hosted zone"
    }
  },

  "Resources" : "COMMENT:リソースを定義します",
  "Resources" : {
    "myDNSRecord" : {
      "Type" : "AWS::Route53::RecordSet",
      "Properties" : {
        "HostedZoneName" : { "Fn::Join" : [ "", [{"Ref" : "HostedZone"}, "." ]]},
        "Comment" : "CNAME redirect to aws.amazon.com.",
        "Name" : { "Fn::Join" : [ "", [{"Ref" : "AWS::StackName"}, ".", {"Ref" : "AWS::Region"}, ".", {"Ref" : "HostedZone"}, "."]]},
        "Type" : "CNAME",
        "TTL" : "900",
        "ResourceRecords" : ["aws.amazon.com"]
      }
    }
  },
  "Outputs" : "COMMENT:ここに書いた出力はCloudFormationのコンソールで見ることができます",
  "Outputs" : {
    "CNAME" : "COMMENT:作成したレコードのCNAMEを表示します",
    "CNAME" : {
      "Value" : { "Ref" : "myDNSRecord" }
    }
  }
}

コマンドラインツールで実行してみます。

$ cfn-validate-template --template-file Route53_CNAME.template
PARAMETERS  HostedZone  false  The DNS name of an existing Amazon Route 53 hosted zone
$ cfn-create-stack ROUTE53-STACK --template-file Route53_CNAME.template --parameters "HostedZone=classmethod.jp;"

スタックが作成され、Route53にもレコードが追加されました。ただ問題が1つありCloudFormationのコンソールで日本語部分が???になっています。

130803-0001

どうやら動作上問題なくても日本語は使わない方が良さそうですね。

IAM

次にIAMで試してみましょう。IAMユーザやRoleに権限を与える際にポリシー設定をJSONで記述しますが、ここでコメントは使えるでしょうか?

130803-0002

130803-0003

日本語が含まれているためでしょうか?エラーになってしまいました。それではコメントをASCII文字列だけにしてみましょう。

130803-0004

130803-0005

IAMはASCII文字列だけでもダメでした。IAMでは重複キーコメントは使えません。やっぱり重複キーをどう扱うかなんて実装によりますよね・・・

chef node.json

chef-soloのコマンドオプションで与えるJSONファイルでも試してみましょう。

{
  "run_list": "TimezoneとLANG設定を日本向けに変更します",
  "run_list":
    [ "timezone", "i18n" ]
}

ファイルをnode.jsonという名前で保存してknife soloを実行します。

$ knife solo bootstrap ec2-54-249-xxx-xxx.ap-northeast-1.compute.amazonaws.com node.json
...
Chef Client finished, 3 resources updated

日本語のコメントもOKでした!

まとめ

まとめると、このような結果になりました。

ツール・サービス ASCIIのみ マルチバイト文字列
jq
CloudFormation △(日本語が???に)
IAM
chef node.json

いろいろ複雑になりがちでコメントを残しておきたいIAMで使えないのが残念です。正直実用レベルで使えそうではないですね。どなたかJSONにコメントをつける良い方法があれば、ぜひ教えてください。