JavascriptでJSON

# はじめに
　JavascriptでJSONを扱う機会が多いのでまとめてみます。mapとかreduceとかそろそろ使いこなせるようになりたいです。


# 前提
　扱うJSONは下のような感じにしました。気分です。最近iPod卒業して以下の3つを品定め中だからです。ランキングは一部抜粋、今Apple Musicに傾きつつあるので、他のやつのランキングはスキップで。まあだいたい同じですし。

```javascript

var sample = {
	Music_Services:[
		{
			Service: "Apple Music",
			Company: "Apple",
			Top_Song_Ranking:{
				observation_date: "2019-02-09",
				ranking:[
					{
						artist: "あいみょん",
						song: "マリーゴールド",
						rank: 1
					},
					{
						artist: "ONE OK ROCK",
						song: "Stand Out Fit In",
						rank: 2
					},
					{
						artist: "あいみょん",
						song: "今夜このまま",
						rank: 3
					},
					{
						artist: "エド・シーラン",
						song: "Shape of You",
						rank: 7
					},
					{
						artist: "あいみょん",
						song: "愛を伝えたいだとか",
						rank: 9
					}
				]
			}
		},
		{
			Service: "Google Play Music",
			Company: "Google",
			Top_Song_Ranking: null
		},
		{
			Service: "Spotify",
			Company: "Spotify AB",
			Top_Song_Ranking: null
		}
	]
}
```

＊ データ構造は適当に作ったものでApple MusicのAPI定義とかに合わせたりしてません。


# 参照
## レコード参照
**「音楽サービスのどんなデータ入ってるのかザーッと見たい」**

```javascript
sample["Music_Services"].forEach((item) => {
	console.log(item)
})
```
↓

```
{ Service: 'Apple Music',
  Company: 'Apple',
  Top_Song_Ranking: 
   { observation_date: '2019-02-09',
     ranking: [ [Object], [Object], [Object], [Object], [Object] ] } }
{ Service: 'Google Play Music',
  Company: 'Google',
  Top_Song_Ranking: null }
{ Service: 'Spotify',
  Company: 'Spotify AB',
  Top_Song_Ranking: null }
```

[Object]の中身表示したかったら```console.log(JSON.stringify(item))``` にすれば見れますね。

## プロパティ参照
**「一覧だと見づらいからどんな属性があるかだけ見たい」**

```javascript
var firstService = sample["Music_Services"][0]
Object.keys(firstService).forEach((data) => {
  console.log(data);
})
```
↓

```
Service
Company
Top_Song_Ranking
```


**「もっと深い属性が見たい」**

```javascript
Object.keys(firstService["Top_Song_Ranking"]).forEach((data) => {
  console.log(data);
})
console.log("====")

var firstSong = firstService["Top_Song_Ranking"]["ranking"][0]
Object.keys(firstSong).forEach((data) => {
  console.log(data);
})
```
↓

```
observation_date
ranking
====
artist
song
rank
```
　基本的に1つ目のレコードだけサンプル的にとってきて中を覗く感じです。レコードによってプロパティに過不足ある場合とかは対象外で。

# 検索
## 単一検索
**「Apple Musicの情報だけ欲しい」**

```javascript
const AppleMusic = sample["Music_Services"].find((item, index) => {
	return (item.Service === "Apple Music")
})
/*こっちでもおなじ
const AppleMusic = sample["Music_Services"].find((item, index) => {
	if(item.Service === "Apple Music") return true
})
*/

console.log(AppleMusic)
```
↓

```
{ Service: 'Apple Music',
  Company: 'Apple',
  Top_Song_Ranking: 
   { observation_date: '2019-02-09',
     ranking: [ [Object], [Object], [Object], [Object], [Object] ] } }
```

ここからはApple Musicしか眼中に入れません。
なので、変数 "AppleMusic"を使いまわします。


## 複数検索
**「あいみょんの曲ってどんぐらいランキング入ってるんだろ」**

```javascript
const Aimyon_Songs = AppleMusic["Top_Song_Ranking"]["ranking"].filter((item, index) => {
	return (item.artist === "あいみょん")
})

console.log(Aimyon_Songs)
```

↓

```
[ { artist: 'あいみょん', song: 'マリーゴールド', rank: 1 },
  { artist: 'あいみょん', song: '今夜このまま', rank: 3 },
  { artist: 'あいみょん', song: '愛を伝えたいだとか', rank: 9 } ]
```

＊本当は他にももっと入ってますよ

**「英語タイトルの曲どんくらいランキング入ってるんだろ」**

```javascript
const English_Titles = AppleMusic["Top_Song_Ranking"]["ranking"].filter((item, index) => {
	return (item.song.match(/[a-zA-Z]/))
})

console.log(English_Titles)
```
↓

```
[ { artist: 'ONE OK ROCK', song: 'Stand Out Fit In', rank: 2 },
  { artist: 'エド・シーラン', song: 'Shape of You', rank: 7 } ]
```

＊おまけ

**filter**は複数検索の時ですね。findも兼ねますが、なんとなく使い分けたいなと。


# 制限
**「曲名だけ一覧でバーっと見たい」**

``` javascript
const song_names = AppleMusic["Top_Song_Ranking"]["ranking"].map(x => x["song"])
console.log(song_names)
```
↓

```
[ 'マリーゴールド',
  'Stand Out Fit In',
  '今夜このまま',
  'Shape of You',
  '愛を伝えたいだとか' ]
```

　**map**って主にこういうときに使うイメージですね。他にもあるかな。



# 集約
**「結局ランキングにどういうアーティストが何曲ずつくらい入ってるんだろ」**

```javascript
const summary = AppleMusic["Top_Song_Ranking"]["ranking"].reduce((accum, current)=> {
    //同じアーティスト名がaccumの中にあるか検索
	const element = accum.find((item) => {return item.artist === current.artist});
    //あったらカウントだけする
	if(element){ element.count ++}
    //なかったらaccumに追加してあげる
	else{
		accum.push({
			artist: current.artist,
			count: 1
		});
	}
	return accum
}, []);

console.log(summary)
```

↓

```
[ { artist: 'あいみょん', count: 3 },
  { artist: 'ONE OK ROCK', count: 1 },
  { artist: 'エド・シーラン', count: 1 } ]
```

　**reduce**は集約するときに使う感じですね。forEachで足していくほうがわかりやすいんですけどreduceが使えたらかっこいいなと。まだまだ慣れません。



# おわりに
　reduceはやはり小難しい。あいみょんすごい。もう少し追記していきたいと思っているところです。

<br>