JSON.stringifyを改めて調べる。


# JSON.stringifyって便利ですよね。

+ 簡単に成形できていい感じです。

```javascript:json.js
var obj = {
	a: 1,
	b: "Moji",
	c: [1, 2, 3, 4],
	d: {
		"A": 1,
		"B": 2
	}
};
console.log(JSON.stringify(obj));
console.log(JSON.stringify(obj,undefined,1));
```

```json:結果
{"a":1,"b":"Moji","c":[1,2,3,4],"d":{"A":1,"B":2}}

{
 "a": 1,
 "b": "Moji",
 "c": [
  1,
  2,
  3,
  4
 ],
 "d": {
  "A": 1,
  "B": 2
 }
}
```

# でも、(obj,undefined,1)ってなんだろ？

+ 何の気なしにundefinedって指定してたんですが、これってホントはなんなんでしょ？

## 仕様を調べてみます。

+ mozillaのサイトを見てみると...
+ [https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)

### 構文

```
JSON.stringify(value[, replacer[, space]])
```

+ replacerってなんでしょ？spaceは字下げっぽいですね。

### 引数

+ value
	+ JSON 文字列に変換する値。
+ replacer ```Optional```
	+ もし関数である場合、文字列化の間に出会った値とプロパティを変換します。もし配列である場合は、最終的な文字列のオブジェクトに含まれるプロパティの集合を指定します。

+ space ```Optional```
	+ 結果の文字列を整形して出力します。

## spaceから試します。


+ 説明がありました。

```
space 引数は最終的な文字列でのスペーシングを調整するために用いることができます。もし数値であれば、文字列化での連続するレベルはそれぞれその量（10 まで）の空白文字でインデントされます。もし文字列であれば、連続するレベルはこの文字列（またはその最初の 10 文字）でインデントされます。
```

+ へー、数字でもいいし、文字でもいいんだ！


#### インデント空白4文字
```json:console.log(JSON.stringify(obj,undefined,4));
{
    "a": 1,
    "b": "Moji",
    "c": [
        1,
        2,
        3,
        4
    ],
    "d": {
        "A": 1,
        "B": 2
    }
}
```

#### インデント空白10文字
```json:console.log(JSON.stringify(obj,undefined,10));
{
          "a": 1,
          "b": "Moji",
          "c": [
                    1,
                    2,
                    3,
                    4
          ],
          "d": {
                    "A": 1,
                    "B": 2
          }
}
```

#### インデント空白100文字

+ 100文字にしても10文字と同じです。

```json:console.log(JSON.stringify(obj,undefined,100));
{
          "a": 1,
          "b": "Moji",
          "c": [
                    1,
                    2,
                    3,
                    4
          ],
          "d": {
                    "A": 1,
                    "B": 2
          }
}
```

#### インデントにタブ文字

```json:console.log(JSON.stringify(obj,undefined,"\t"));
{
	"a": 1,
	"b": "Moji",
	"c": [
		1,
		2,
		3,
		4
	],
	"d": {
		"A": 1,
		"B": 2
	}
}
```

#### インデントに記号

+ JSONフォーマットじゃなくなりますがこんなのでもできました！

```json:console.log(JSON.stringify(obj,undefined,"🐻"));
{
🐻"a": 1,
🐻"b": "Moji",
🐻"c": [
🐻🐻1,
🐻🐻2,
🐻🐻3,
🐻🐻4
🐻],
🐻"d": {
🐻🐻"A": 1,
🐻🐻"B": 2
🐻}
}
```

## replacerとは？？

+ replacerには関数か配列が使えてjsonの置き換え（フィルター？）ができるようです。

### replacer関数を使ってみます。

+ replacerは、key,valueの値をとって、stringであれば無効（？）にしてそれ以外はvalueを返すという意味です。

```javascript:replacer関数

function replacer(key, value) {
	if (typeof value === 'string') {
		return undefined;
	}
	return value;
}

var obj = {
	a: 1,
	b: "Moji",
	c: [1, 2, 3, 4],
	d: {
		"A": 1,
		"B": 2
	}
};

console.log(JSON.stringify(obj, replacer, "\t"));
```

```json:結果
{
	"a": 1,
	"c": [
		1,
		2,
		3,
		4
	],
	"d": {
		"A": 1,
		"B": 2
	}
}
```

+ 文字が無くなりましたね！

### replacerの配列？

+ 配列ってなんでしょ？

```javascript:replacer配列

var replacer = ['a','d','A'];

var obj = {
	a: 1,
	b: "Moji",
	c: [1, 2, 3, 4],
	d: {
		"A": 1,
		"B": 2
	}
};

console.log(JSON.stringify(obj, replacer, "\t"));
```
```json:結果
{
	"a": 1,
	"d": {
		"A": 1
	}
}
```
+ なるほど！指定のkeyだけフィルタされるんですね！

### replacer関数 応用編

+ 関数なのでいろいろいじれちゃいますね。

```javascript:replacer
function replacer(key, value) {
	var ret = value;
	var now = String(new Date());
	if (key === 'A') { // key:Aの値は現在時刻に
		ret = now;
	} else if (typeof value === 'number') { // 数値は文字列に変換
		ret = String(value);
	}
	return ret;
}
```

```json:こんな結果になりました。
{
	"a": "1",
	"b": "Moji",
	"c": [
		"1",
		"2",
		"3",
		"4"
	],
	"d": {
		"A": "Wed Feb 17 2016 23:12:21 GMT+0900 (JST)",
		"B": "2"
	}
}
```

+ ちゃんと数値が"文字列"になり、"A"の値がDateになりました。

### replacer関数は全要素を舐める

+ この挙動からわかるようにreplacerは全要素を舐めてくれます。

```javascript:全要素

function replacer(key, value) {
	console.log("key:[" + key + "]\t type:[" + (typeof value) + "]\tvalue:[" + value + "]");
	return value;
}

JSON.stringify(obj, replacer, "\t");
```

```shell:ツリーでたどっていくみたい
key:[]	 type:[object]	value:[[object Object]]
key:[a]	 type:[number]	value:[1]
key:[b]	 type:[string]	value:[Moji]
key:[c]	 type:[object]	value:[1,2,3,4]
key:[0]	 type:[number]	value:[1]
key:[1]	 type:[number]	value:[2]
key:[2]	 type:[number]	value:[3]
key:[3]	 type:[number]	value:[4]
key:[d]	 type:[object]	value:[[object Object]]
key:[A]	 type:[number]	value:[1]
key:[B]	 type:[number]	value:[2]
```

## まとめ

+ replacerって便利！！
+ 表示だけならいいけど、これでフィルタして再利用するのは、なんかちょっと危険な予感...