質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Q&A

解決済

4回答

5159閲覧

rubyを用いて、jsonファイルを加工するプログラムを作成したいです。

kento2543

総合スコア163

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

0グッド

1クリップ

投稿2015/04/21 11:32

編集2015/04/21 13:26

rubyを用いて、jsonファイルを加工するプログラムを作成したいです。
やりたいことと致しましては
2つ以上のファイルのjsonファイルをして必要なデータのみ抽出し、
別のファイルとして出力したいです。(テキストファイルなり、csv、json等)

以下にあるファイル名でいうと、
hoge1.jsonファイルの"name":"函館朝市"

をトリガーとし、

hoge2.jsonの
"name":"函館朝市"の"ken"である"北海道"を取得したいです。

そしてテキストファイルに以下のように出力したいです。

ken:北海道
name:函館朝市

実際にやろうとすることは、もっとデータが多いため、複雑になっております。
今回は、あくまでシンプルにするため、このような形態にしております。

そのため別の例を出すと、
"name":"名古屋市"という情報から、
"ken":"名古屋"
というのを取得したりしたいです。

データベースのカラムのような要領で、同じカラムをトリガーとして、関連する情報を
取得するプログラムをrubyで作成したいのですが、やり方がわかりません。

もしご存知の方は、知恵をお貸し頂けないでしょうか?

わかりにくいかと思いますので、質問して頂けると回答致します。

また、私は最近API等に興味があるため、
こういうのを応用して、Jsonを用いて、データの加工などをやっていきたいと考えております。

皆様はそういうのをやられたりしますか?
もしやられていたら、どういうことをなさっていたのかもお答え頂けると嬉しいです。

今後の参考にしていきたいと考えております。


ファイル名;hoge1.json
{
"marker":[
{"lat":41.772596,"lng":140.725261,"name":"函館朝市"},
{"lat":41.796864,"lng":140.756965,"name":"五稜郭"},
{"lat":41.772912,"lng":140.816231,"name":"函館空港"}
]
}

ファイル名;hoge2.json
{
"hokkaido":[
{"name":"函館朝市"},
{"ken":"北海道"},
{"zinkou":200000}
]
}


追記

皆様、素晴らしいコード有難う御座います。
こんなコードがかければなと圧巻しております。

さて、追加で大変恐縮ですが、今回、JSONを以下のようにコードの中に直接代入する形で記述されておりますが、hoge1.json といったファイル名をコードに入れて、その中身を markers = JSON.parse というふうにできないでしょうか?

イメージとしては、以下のような感じです。
markers = JSON.parse(hoge1.json)

実際に扱うJSONは30行ほどあり、かつ、日によって増えていくため、
ファイル名から中身を取り出して、パースする処理をしたいです。

もし宜しければ、再度お知恵をお借りできないでしょうか?

何卒宜しくお願いします。

('{
"marker":[
{"lat":41.772596,"lng":140.725261,"name":"函館朝市"},
{"lat":41.796864,"lng":140.756965,"name":"五稜郭"},
{"lat":41.772912,"lng":140.816231,"name":"函館空港"},
{"lat":1.000000,"lng":1.000000,"name":"千葉市"}
]
}')

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

1.json, 2,json, 1.rb を示します。(ruby のコードは冗長になってますが、素直に書いてみています)
1.json

lang

1{"marker":[{"lat":41.772596,"lng":140.725261,"name":"函館朝市"},{"lat":41.796864,"lng":140.756965,"name":"五稜郭"},{"lat":41.772912,"lng":140.816231,"name":"函館空港"}]}

2.json

lang

1{"hokkaido":[{"name":"函館朝市"},{"ken":"北海道"},{"zinkou":200000}]}

1.rb

lang

1# coding: utf-8 2require 'json' 3 4json_files = ['1.json', '2.json'] # 入力ファイル 5out_file = '3.json' # 出力ファイル 6 7infos = [] 8# json の読込み 9json_files.each do |f| 10 infos << open(f) do |io| 11 JSON.load(io) 12 end 13end 14 15# 2.json の構造を処理しやすいように変更する。 16ary = [] 17infos[1].each do|key, mark| 18 hash = {} 19 # hash の配列を 1 つの hash に構成しなおす 20 # [{"name":"函館朝市"}, {"ken":"北海道"}, {"zinkou":200000}] 21 # ==> {name => '', ken => '', zinkou => ''} 22 mark.each do|m| 23 m.each do|k, v| 24 hash[k.to_sym] = v 25 end 26 end 27 ary << hash 28end 29# p ary 30 31ans = {} 32# 1.json の name に対応する 2.json の ken を得る。 33infos[0]['marker'].each do |mark| 34 target_name = mark['name'] 35 ary.each do |a| 36 ans[target_name] = a[:ken] if a[:name] == target_name 37 end 38end 39p ans 40 41# json 形式で保存 42open(out_file, 'w') do |f| 43 JSON.dump(ans, f) 44end

実行すると画面には "{"函館朝市"=>"北海道"}" と表示されます。
3.json として、次の内容が出力されます。

lang

1{"函館朝市":"北海道"}

投稿2015/04/21 14:16

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

hoge2.jsonの形式がおかしい気がしますが、200,000 は、200000"200,000"の書き誤りとして、他は書かれた通りだとすると、

lang

1require "json" 2 3x1 = JSON.load(IO.read("hoge1.json")) 4x2 = JSON.load(IO.read("hoge2.json")) 5 6mark2ken = x2.each_with_object({}){|(x,y),a| a[y[0]["name"]]=y[1]["ken"]} 7 8x1["marker"].each do |mark| 9 p mark2ken[mark["name"]] 10end

投稿2015/04/21 13:03

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kento2543

2015/04/21 13:25

すごくコンパクトなコードを有難う御座います。こんなに短く表現できるというのはすごいです。皆様のコードを見ていると、人それぞれ違うのだなって改めて気づかせられます。 またご指摘有難う御座います。 「200,000」 は、「200000」の間違えです。 一人で悩んでいて進まなかったのですが、これでJSONの加工に着手出来そうです。 大変感謝しております。有難う御座います。
guest

0

lang

1# coding: utf-8 2require 'json' 3hoge1 = JSON.parse('{ 4 "marker":[ 5 {"lat":41.772596,"lng":140.725261,"name":"函館朝市"}, 6 {"lat":41.796864,"lng":140.756965,"name":"五稜郭"}, 7 {"lat":41.772912,"lng":140.816231,"name":"函館空港"}, 8 {"lat":1.000000,"lng":1.000000,"name":"千葉市"} 9 ] 10}') 11hoge2 = JSON.parse('{ 12 "hokkaido":[ 13 {"name":"函館朝市"}, 14 {"ken":"北海道"}, 15 {"zinkou":200000} 16 ], 17 "chiba":[ 18 {"name":"千葉市"}, 19 {"ken":"千葉県"}, 20 {"zinkou":100000} 21 ] 22}') 23#hoge1から全てのnameを取得 24keys = hoge1['marker'].map{ |e| e['name'] } 25 26#欲しい情報を指定 27info = 'ken' 28 29#keysの要素を回しhoge2のnameの一致を検索し出力 30keys.map do |key| 31 hoge2.select{|k, v| v[0]['name'] == key }.each{ |k, v| puts v[1][info] } 32end 33 34#=>北海道 35#=>千葉県

投稿2015/04/21 12:57

syokeinin

総合スコア74

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kento2543

2015/04/21 13:15

早速のご回答ありがとうございます。 見通しの良いコードで直感的に理解できました。 投稿してから1時間程度(実際はもっと少ないのかもしれませんが)でこのようなコードがかけるなんて今の自分では理解ができませんでした(笑) 追加で恐縮ですが、今回、JSONを以下のようにコードの中に直接代入する形で記述されておりますが、hoge1.json といったファイル名をコードに入れて、その中身を markers = JSON.parse というふうにできないでしょうか? イメージとしては、以下のような感じです。 markers = JSON.parse(hoge1.json) 実際に扱うJSONは30行ほどあり、かつ、日によって増えていくため、 ファイル名から中身を取り出して、パースする処理をしたいです。 もし宜しければ、再度お知恵をお借りできないでしょうか? 何卒宜しくお願いします。 JSON { "marker":[ {"lat":41.772596,"lng":140.725261,"name":"函館朝市"}, {"lat":41.796864,"lng":140.756965,"name":"五稜郭"}, {"lat":41.772912,"lng":140.816231,"name":"函館空港"} ] } JSON ちなみに追加で恐縮ですが、今回、JSONを以下のようにコードの中に直接代入する形で記述されておりますが、hoge1.json といったファイル名をコードに入れて、その中身を markers = JSON.parse というふうにできないでしょうか? イメージとしては、以下のような感じです。 markers = JSON.parse(hoge1.json) 実際に扱うJSONは30行ほどあり、かつ、日によって増えていくため、 ファイル名から中身を取り出して、パースする処理をしたいです。 もし宜しければ、再度お知恵をお借りできないでしょうか? 何卒宜しくお願いします。 ('{ "marker":[ {"lat":41.772596,"lng":140.725261,"name":"函館朝市"}, {"lat":41.796864,"lng":140.756965,"name":"五稜郭"}, {"lat":41.772912,"lng":140.816231,"name":"函館空港"}, {"lat":1.000000,"lng":1.000000,"name":"千葉市"} ] }')
guest

0

ベストアンサー

hoge2.json の2つ以上のデータがある場合のJSONを教えてもらえますか?


とりあえずこんな感じで。

スクリプト

lang

1require 'json' 2 3markers = JSON.parse <<-JSON 4{ 5 "marker":[ 6 {"lat":41.772596,"lng":140.725261,"name":"函館朝市"}, 7 {"lat":41.796864,"lng":140.756965,"name":"五稜郭"}, 8 {"lat":41.772912,"lng":140.816231,"name":"函館空港"} 9 ] 10} 11JSON 12 13prefs = JSON.parse <<-JSON 14{ 15 "hokkaido":[ 16 {"name":"函館朝市"}, 17 {"ken":"北海道"}, 18 {"zinkou":200000} 19 ] 20} 21JSON 22 23mark = markers['marker'][0] 24puts "-- mark" 25p mark 26 27def find_prefs(name, prefs) 28 prefs.each do |label, values| 29 values.each do |a_hash| 30 a_hash.each do |k, v| 31 if k == 'name' && v == name 32 return { label => values } 33 end 34 end 35 end 36 end 37 nil 38end 39 40puts "-- search result" 41p find_prefs(mark['name'], prefs) 42p find_prefs('unknown', prefs) 43 44# -------------------------------- 45prefs_2 = prefs.map{ |k, v| [k, v.inject(:merge)] }.to_h 46puts "=== better structure" 47puts "-- all data" 48p prefs_2 49 50def find_prefs2(name, prefs_2) 51 prefs_2.each do |label, values| 52 return values if values['name'] == name 53 end 54 nil 55end 56 57pref_data = find_prefs2(mark['name'], prefs_2) 58puts "-- found data" 59p pref_data 60puts "-- ken" 61p pref_data['ken']

結果

-- mark {"lat"=>41.772596, "lng"=>140.725261, "name"=>"函館朝市"} -- search result {"hokkaido"=>[{"name"=>"函館朝市"}, {"ken"=>"北海道"}, {"zinkou"=>200000}]} nil === better structure -- all data {"hokkaido"=>{"name"=>"函館朝市", "ken"=>"北海道", "zinkou"=>200000}} -- found data {"name"=>"函館朝市", "ken"=>"北海道", "zinkou"=>200000} -- ken "北海道"

投稿2015/04/21 12:31

編集2015/04/21 12:43
hello-world

総合スコア1342

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kento2543

2015/04/21 13:12

早速の投稿ありがとうございます。こんなにスラスラ書けてしまうとは圧巻でした。 >hoge2.json の2つ以上のデータがある場合のJSONを教えてもらえますか? 今回のhoge.jsonというのは質問用に仮で作ったJSONになります。 そのため、申し訳ありませんが2つ以上のデータというのは今のところありません。 しかし、大変わかり易いコードですので、これを元に、私の方でも頑張ってみようと思います。 追加で恐縮ですが、今回、JSONを以下のようにコードの中に直接代入する形で記述されておりますが、hoge1.json といったファイル名をコードに入れて、その中身を markers = JSON.parse というふうにできないでしょうか? イメージとしては、以下のような感じです。 markers = JSON.parse(hoge1.json) 実際に扱うJSONは30行ほどあり、かつ、日によって増えていくため、 ファイル名から中身を取り出して、パースする処理をしたいです。 もし宜しければ、再度お知恵をお借りできないでしょうか? 何卒宜しくお願いします。 JSON { "marker":[ {"lat":41.772596,"lng":140.725261,"name":"函館朝市"}, {"lat":41.796864,"lng":140.756965,"name":"五稜郭"}, {"lat":41.772912,"lng":140.816231,"name":"函館空港"} ] } JSON
hello-world

2015/04/21 13:19

prefs = JSON.parse(File.read('pref.json')) でファイルを読み込めます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問