JSONをrubyのhashに読み書きしやすい形で変換する

  • 1
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

背景

jsonをrubyのhashに変換したい。このとき、変換結果をソースコードに残し、さらにエディタで編集を加えたい。そのため、読みやすいだけでなく、編集しやすい形に変換する必要がある。

ppawesome_print使用すると、インデントと改行が挿入されたりして読みやすくはなるものの、普段書くようなhashの形には整形されない。

今回はawesome_printrubocopを使って、jsonを読みやすいhashに変換してみる。

変換例

今回は以下のようにjsonをhashにするような処理を作る。

変換前

input.json
{
  "AWSTemplateFormatVersion": "2010-09-09",

  "Resources": {
    "InstanceSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Enable SSH access and HTTP access on the configured port",
        "SecurityGroupIngress": [ 
          { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": { "Ref" : "SSHLocation" } },
          { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0" }
        ]
      }
    }
  }
}

変換後

output.rb
{
  AWSTemplateFormatVersion: '2010-09-09',
  Resources: {
    InstanceSecurityGroup: {
      Type: 'AWS::EC2::SecurityGroup',
      Properties: {
        GroupDescription: 'Enable SSH access and HTTP access on the configured port',
        SecurityGroupIngress: [
          {
            IpProtocol: 'tcp',
            FromPort: '22',
            ToPort: '22',
            CidrIp: {
              Ref: 'SSHLocation'
            }
          },
          {
            IpProtocol: 'tcp',
            FromPort: '80',
            ToPort: '80',
            CidrIp: '0.0.0.0/0'
          }
        ]
      }
    }
  }
}

変換方法

以下の方法で上記のように変換できる。

  1. JSON.parseでjsonをhashに変換し、
  2. awesome_printでpretty printし
  3. rubocop --auto-correctで整える

実行例

事前に変換したいjsonを用意する。下記の実行例ではinput.jsonとして用意した前提で話をすすめる。

$ gem install awesome_print rubocop
$ wget https://gist.githubusercontent.com/keqh/5507d510ae5b68ca315f98844f2f612d/raw/c2007218f9399142fbe42085d9a7413637e72fd9/convert_json_into_rb.rb
$ chmod 755 convert_json_into_rb.rb
$ convert_json_into_rb.rb input.json output.rb

ソースコード

下記のソースコードはgistにjsonをrubyのhashに読み書きしやすい形で出力するスクリプトとしても載せている。

convert_json_into_rb.rb
#!/usr/bin/env ruby
# require: awesome_print, rubocop

require 'ap'
require 'json'

if ARGV.count != 2
  puts 'usage: ./script.rb <input_json_file> <output_sour_file_name>'
  exit 1
end

INPUT_JSON_FILE = ARGV[0]
OUTPUT_SOURCE_FILE = ARGV[1]

contents = File.read(INPUT_JSON_FILE)
output = JSON.parse(contents, symbolize_names: true).ai(index: false, plain: true, indent: 2)
File.write(OUTPUT_SOURCE_FILE, output)
system("rubocop #{OUTPUT_SOURCE_FILE} --auto-correct --format disabled")