4
3

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 3 years have passed since last update.

WinMergeでJSONデータを整形して比較する

Last updated at Posted at 2020-05-09

JSONデータの比較

2021/10/13 追記
WinMerge 日本語版の2021/06/29 2.16.12-jp-3でPrettifyJSON展開プラグインが追加されたので、デフォルトでJSON整形比較が可能になりましたね!


BeatSaberで遊ぶようになってからJSONファイルに触れる機会が増えたのですが、吐き出すツールによって未整形のJSONデータである場合があります。代表的なのは、譜面データの.datファイルですね。

Gitで作譜中の譜面データを管理しようと思ったけど、MMA2で保存されるJSONデータが未整形なためWinMergeで差分比較するのが困難になってます。
image.png

WimMergeのプラグインで比較前整形

WinMergeにはプラグイン機能があって、標準でEXCEL等の比較には対応していますので、それを真似てJSONデータを整形してから比較できないか調べたら、既に行っている人がいたのですが、下記エラーが出て上手く動作しませんでした。
image.png
エラーコードを調べるとSyntax errorっぽいのですが、WinMergeからのエラーメッセージが不親切でコードのどこがおかしいのか分からないです。VBScriptとJScriptに分けてCScriptで実行してみたりしましたが特にエラーも出ず、デバッグが難しそうでした。また、64bit環境ではVBScriptからJScriptの関数呼び出しが出来ない様な情報もあるため、あきらめました。

別の方法を調査するとコマンドラインで動く、JSON整形・集計ツールであるjqを見つけたので、これをVBScriptから外部コマンドで呼び出せば行けそうです。

CompareJsonFiles.sct
<scriptlet>
 
<implements type="Automation" id="dispatcher">
    <property name="PluginEvent">
        <get/>
    </property>
    <property name="PluginDescription">
        <get/>
    </property>
    <property name="PluginFileFilters">
        <get/>
    </property>
    <property name="PluginIsAutomatic">
        <get/>
    </property>
    <method name="UnpackFile"/>
    <method name="PackFile"/>
</implements>
 
<script language="VBS">
 
Option Explicit
 
Function get_PluginEvent()
    get_PluginEvent = "FILE_PACK_UNPACK"
End Function
 
Function get_PluginDescription()
    get_PluginDescription = "Json形式のファイルを整形し比較をする"
End Function
 
Function get_PluginFileFilters()
    get_PluginFileFilters = "\.json$;\.dat$"
End Function
 
Function get_PluginIsAutomatic()
    get_PluginIsAutomatic = True
End Function
 
Function UnpackFile(fileSrc, fileDst, pbChanged, pSubcode)
    Dim shell
    Dim command
    Dim jqPath
    jqPath = "C:\Program Files\WinMerge\MergePlugins\jq-win64.exe"
    Set shell = CreateObject("WScript.Shell")
    command = "cmd /c type """ & fileSrc & """ | """ & jqPath & """ > """ & fileDst & """"
    shell.Run command, 0, true
    pbChanged = True
    pSubcode = 0
    UnpackFile = True
End Function
 
Function PackFile(fileSrc, fileDst, pbChanged, pSubcode)
    PackFile = False
End Function
 
</script>
</scriptlet>

ダウンロードしたjqの実行ファイルはWinMergeのプラグインフォルダに置くことにしました。PATHが通ったところに置けばフルパス指定で実行しなくても大丈夫ですが、PC移行時とか忘れちゃうのでプラグインフォルダにCompareJsonFiles.sctと一緒に入れておくことにします。

ハマったところは、shell.Runの部分で shell.Run(command,0,true)だと 0x800a0414 コンパイルエラーになります。これもまたエラーコードしか出ないので非常にデバッグしづらいです。

拡張子フィルタがありますので"\.json$;\.dat$"の部分でJSONファイルに使われる拡張子を列挙すると良いです。BeatSaberで使うことを想定しているので、.datを追加しておきました。

プラグインの使用方法

  1. jqの公式サイトからWindows(64bit)用のexeファイルをダウンロードして、WinMergeのプラグインフォルダに配置します。
  2. 上記プラグインのスクリプトレットをCompareJsonFiles.sctで、同じくプラグインフォルダに配置します。その際にスクリプトのjqPath = "C:\Program Files\WinMerge\MergePlugins\jq-win64.exe"を環境に合わせて修正して下さい。なお、文字コードはSJISにして下さい。
  3. WimMerge起動時のダイアログにあるファイル展開プラグインか、TortoiseGitで差分表示した場合などは起動後にメニューのプラグインから展開プラグインで開くを選択して、CompareJsonFiles.sctを選んで下さい。
    image.png

4.上手く行けば、下記の様にJSONデータが整形されて表示されます。
image.png
5.WinMergeの設定で、指定get_PluginFileFilters拡張子の場合は自動で展開プラグインを適用させることもできますが、必要な場合のみ使用したいので私は手動で整形実行しています。

WinMergeで整形後データを編集した場合

WinMergeで展開プラグインを使用したファイルを編集して保存しようとすると、以下の様なメッセージが表示されます。
image.png
しかし、JSONファイルを整形しているだけなので、そのままOKで同名ファイルに上書き保存すれば問題ありません。

その他

jqコマンドはJSONの整形だけでなくソートなどもできます。
例えばキー基準でソートを行い、構造的な比較をしたい場合は以下の様にスクリプトのjqコマンドを実行している部分を修正すれば可能です。

    command = "cmd /c type """ & fileSrc & """ | """ & jqPath & """ --sort-keys > """ & fileDst & """"

参考:jqでsortする https://qiita.com/yoza/items/c4c732779a5a10fd3b4c

4
3
1

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?