Edited at

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

More than 1 year has passed since last update.


背景

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, ruby19_syntax: true)
File.write(OUTPUT_SOURCE_FILE, output)
system("rubocop #{OUTPUT_SOURCE_FILE} --auto-correct --format disabled")