FortranでJSONなファイルを使う


[JSONパーサがFortranでも提供されている](https://github.com/jacobwilliams/json-fortran)ので，その使い方のメモ．
JSON-Fortran 5.0.0未満を使う場合は[Fortran で JSON を読む](https://qiita.com/chirimen/items/0492033efdf73459cf6f)を参照されたい．
ここでは，2020年01月23日現在の最新版である JSON-Fortran 7.1.0 の使い方を書く．
コンパイラは Intel Fortran Compiler 19.0.4.243 を使用する．

#使い方

ここでは，`home`ディレクトリに`temptemp`ディレクトリを作成して実験する．
JSON-Fortranにはテストコードが添付されているので，
そのうちの1つ，`src/tests/jf_test_01.F90`をコンパイル＆実行する．

以下に2つの方法を示す．


##方法1：とにかく動くとこだけ見たい
という人は以下参照．

```:ダウンロードとテストコードのコンパイル
$ cd ~
$ mkdir temptemp
$ cd temptemp
$ git clone https://github.com/jacobwilliams/json-fortran.git
$ cd json-fortran/src
$ cp tests/jf_test_01.F90 ./
$ ifort json_kinds.F90 json_parameters.F90 json_string_utilities.F90 json_value_module.F90 json_file_module.F90 json_module.F90 jf_test_01.F90
```

ここで，`ifort`に食わせる`.F90`ファイルの順序は大切なので注意．
成功すると`a.out`が作成される．

```:テストコードの実行
$ cd ~/temptemp/json-fortran/src
$ ./a.out
```

ごちゃああと出てきたら成功．


##方法2：コンパイル時間短くしたい
という人は以下のようにしてライブラリを作ればよい．
`xiar`を用いて静的リンクライブラリを生成する．
常用するならこちら．

```:ダウンロードとライブラリファイルの作成
$ cd ~
$ mkdir temptemp
$ cd temptemp
$ git clone https://github.com/jacobwilliams/json-fortran.git
$ cd json-fortran/src
$ ifort json_kinds.F90 json_parameters.F90 json_string_utilities.F90 json_value_module.F90 json_file_module.F90 json_module.F90 -c
$ xiar rc jsonfortran.a json_kinds.o json_parameters.o json_string_utilities.o json_value_module.o json_file_module.o json_module.o
```
ここで，`ifort`に食わせる`.F90`ファイルの順序は大切なので注意．これにより
`jsonfortran.a`
`json_kinds.mod`
`json_parameters.mod`
`json_string_utilities.mod`
`json_value_module.mod`
`json_file_module.mod`
`json_module.mod`
が生成される．
`jsonfortran.a`と`.mod`ファイルのパスを指定してコンパイル．

```:テストコードのコンパイル
$ cd ~/temptemp/json-fortran/src/tests
$ ifort jf_test_01.F90 ~/temptemp/json-fortran/src/jsonfortran.a -I ~/temptemp/json-fortran/src/
```

エラーが生じず`a.out`ができれば成功．

```:テストコードの実行
$ cd ~/temptemp/json-fortran/src/tests
$ mv a.out ../
$ cd ..
$ ./a.out
```

ごちゃああと出てきたら成功．



#使用例

種々のパラメータや計算条件などをファイルから読み込みたいという人は多いはず．
ここではとりあえず，上記の方法1でまるごとコンパイルするやり方で書いた．
もちろん，ライブラリ化したものをリンクする方がビルドが早い．

##JSONファイル読み込み用の最小限コード

```json_test.f90
program json_test
  use json_module ! JSON-Fortran モジュール
  use, intrinsic :: iso_fortran_env, only : output_unit ! PRINTで使われる装置
  implicit none
  type(json_file) :: json ! JSONパーサ
  character(kind=json_CK,len=:), allocatable :: s ! 文字列用
  real(kind=json_RK) :: a ! 実数用
  real(kind=json_RK), dimension(:), allocatable :: b ! 実数の配列用
  logical(kind=json_LK) :: fl ! 論理用
  integer :: i ! do文用

  call json%initialize() ! モジュール初期化

  call json%load(filename='test.json') ! JSONファイルを読み込む
  call json%print_error_message(output_unit) ! パースエラーがあれば表示

  call json%print(output_unit) ! 読み込んだjsonをそのまま表示
  call json%print_error_message(output_unit)

  ! 色々なkeyを取得して変数に格納し，その後表示

  call json%get('title',s)
  call json%print_error_message(output_unit)
  write(output_unit,*) s

  call json%get('model parameters.lattice constant',a)
  call json%print_error_message(output_unit)
  write(output_unit,*) "lattice constant = ",a

  call json%get('model parameters.chemical potentials',b)
  call json%print_error_message(output_unit)
  write(output_unit,*) "chemical potentials"
  do i=lbound(b,1), ubound(b,1)
    write(output_unit,*) b(i)
  enddo

  call json%get('flag1',l)
  call json%print_error_message(output_unit)
  write(output_unit,*) "flag1 = ",l

  call json%get('flag2',l)
  call json%print_error_message(output_unit)
  write(output_unit,*) "flag2 = ",l


  ! 後処理
  call json%destroy()
  call json%print_error_message(output_unit)

end program json_test

```


```test.json
{
    ! コメント：パースエラーにならずに使用可能
    "title":"This is a test.",
    "model parameters":{
        "lattice constant":1.0,
        "chemical potentials":[1,2,3,4,5,], ! ケツカンマ使える
    },
    "flag1":"true",
    "flag2":"false", ! ケツカンマ使える
}
```

上記の2個のファイルとJSON-Fortranソース一式を同じディレクトリに保存し，コンパイルする．

```
$ ls
json_file_module.F90                 json_parameters.F90
json_initialize_arguments.inc        json_string_utilities.F90
json_initialize_dummy_arguments.inc  json_test.f90
json_kinds.F90                       json_value_module.F90
json_macros.inc                      test.json
json_module.F90
$ ifort json_kinds.F90 json_parameters.F90 json_string_utilities.F90 json_value_module.F90 json_file_module.F90 json_module.F90 json_test.f90
```
実行結果：

```
$ ./a.out
{
  "title": "This is a test.",
  "model parameters": {
    "lattice constant": 0.1E+1,
    "chemical potentials": [
      1,
      2,
      3,
      4,
      5
    ]
  },
  "flag1": "true",
  "flag2": "false"
}
 This is a test.
 lattice constant =    1.00000000000000
 chemical potentials
   1.00000000000000
   2.00000000000000
   3.00000000000000
   4.00000000000000
   5.00000000000000
 flag1 =  T
 flag2 =  F
$
```

ケツカンマやコメントが排除された「真っ当な」JSON形式で正しくパース＆プリントされているヤッター！
JSON形式でのファイル出力や，書き換えも当然可能：`jf_test_01.F90`その他を参照して真似すればよい．
`json_RK`や`json_LK`，`json_CK`などは`json_kinds.F90`を参照されたい：
例えば，コンパイラオプションなしでは`json_RK=real64`に選択され，倍精度実数型となる．