5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSON同士の比較はYAMLが良い - WEBツール(JS)で「JSON⇒YAML」変換時に完全なエスケープ戻しを目指す

Posted at

WEBツール

API等のデータのやり取りは主にJSONを利用しているが、人の目で見たり比較する時はYAMLが便利です。
YAMLはエスケープされた記号(改行=「\n」等)をエスケープ前に戻したデータで表現ができるのがいいところですね。

:point_right_tone3: そこで、JSON→YAML→そのまま比較するWEBツールを作りました。
https://rawseq.github.io/json-diff/
変換機能はjs-yaml,比較ツールはmonacoを利用しています。

既に他のWEBツールやLive Demoで体験済かもしれませんが、「エスケープ文字が戻らない場合があるのでは?」という不安を持っている方がいると思いますが、だまされたと思って一度使ってみてください。(そして戻らなければ教えてください><;)

※Chrome推奨。monacoの仕様でA→Bの比較、Bの編集しかできません。(編集したBをJSONでコピーすることはできます)

JavascriptでJSONからYAMLに変換する

Javascript上のJSON YAML変換は特殊記号類の変換がくせものです。
JSON-YAML変換は「js-yaml」以外にもいろいろあるのですが、特殊文字が含まれる場合に動作不良になるケースが見受けられました。その中でも一番有望に見えたのが「js-yaml」でした。

しかしながら、「js-yaml」でも理想の動作をしてくれない場合があります。
例えば:point_down_tone3:のJSONをYAMLに変換しようとすると

JSONサンプル
{"data":"\u6539\u884c\uff1a\n\u30bf\u30d6\uff1a\t\n\u30b9\u30e9\u30c3\u30b7\u30e5\uff1a/\n\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\uff1a\\\n\u30b7\u30f3\u30b0\u30eb\u30af\u30a9\u30fc\u30c8\uff1a'\n\u30c0\u30d6\u30eb\u30af\u30a9\u30fc\u30c8\uff1a\"\n\u30d0\u30c3\u30af\u30af\u30a9\u30fc\u30c8\uff1a`\n\u30c9\u30eb\u8a18\u53f7\uff1a$\n\u30a2\u30c3\u30c8\u30de\u30fc\u30af\uff1a@\n\u4e2d\u62ec\u5f27\uff1a{}\n\u30b3\u30ed\u30f3\uff1a:\n\u7d75\u6587\u5b57\uff1a\u270c\n\u591a\u91cd\u30a8\u30b9\u30b1\u30fc\u30d7\u3055\u308c\u305f\u30bf\u30d6\uff1a\\t"}

:point_down_tone3:こんな感じになります。

js-yamlプレーンで変換したYAML
data: "改行:\nタブ:\t\nスラッシュ:/\nバックスラッシュ:\\\nシングルクォート:'\nダブルクォート:\"\nバッククォート:`\nドル記号:$\nアットマーク:@\n中括弧:{}\nコロン::\n絵文字:✌\n多重エスケープされたタブ:\\t"

これではたとえ仕様上問題ないとしても、比較や目視では使えません。
そこで、修正を加えた後に変換したYAMLが:point_down_tone3:こちら

js-yaml修正後のYAML
data: |-
  改行:
  タブ:	
  スラッシュ:/
  バックスラッシュ:\
  シングルクォート:'
  ダブルクォート:"
  バッククォート:`
  ドル記号:$
  アットマーク:@
  中括弧:{}
  コロン::
  絵文字:✌
  多重エスケープされたタブ:\t

きれいにエスケープが戻るようになりました。
js-yamlでエスケープが戻らなかった原因は「\t」タブコード。
YAML変換前にタブを別な任意文字に変換。変換後に任意文字から戻す処理を加えています。
多重エスケープのタブを除外しているので少し歪になっていますが、

JSONからYAML変換(デコード版)
/**
 * JSON to YAML
 * @param string val 入力
 * @return string 出力
*/
function jtoy(val){
	try{
		return jsyaml.dump(
			JSON.parse(
				val
				.replace(/([^\\])\\t/g,"$1<<TAB>>")
				.replace(/([^\\])\\t/g,"$1<<TAB>>")
				.replace(/^\\t/g,"<<TAB>>")
			)
		).replace(/<<TAB>>/g,"\t");
	}catch(e){
		alert(e.message);
	}
}

おまけ(YAML⇒JSON変換時の文字列エンコード)

JavascriptのJSONオブジェクトやMDNのポリフィルではUnicode文字列のエンコードがかからなかったので、つけてみました。

エンコード

/**
 * YAML to JSON
 * @param string val 入力
 * @return string 出力
*/
function ytoj(val){
	try{
		return unicodeEscape(JSON.stringify(jsyaml.load(val)));
	}catch(e){
		alert(e.message);
	}
}

function unicodeEscape(str){
	var code, pref = {1: '\\x0', 2: '\\x', 3: '\\u0', 4: '\\u'};
	return str.replace(/[^\u0020-\u007e]/g, function(c) {
		return pref[(code = c.charCodeAt(0).toString(16)).length] + code;
	});
}

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?