0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReScriptでJSONをparseする

Posted at

以下のJSONをparseすることを考えます。

json_test.res
let cotoha_result = (`
{
  "result": [
    {
      "chunk_info": {"id": 0, "links": []},
      "tokens": [{"form": "公園"}, {"form": "から"}, {"form": "、"}]
    },
    {
      "chunk_info": {"id": 1, "links": []},
      "tokens": [{"form": "望遠鏡"}, {"form": "で"}]
    },
    {
      "chunk_info": {"id": 2, "links": []},
      "tokens": [{"form": "星"}, {"form": "を"}]
    },
    {
      "chunk_info": {"id": 3, "links": [{"link": 1, "label": "implement"}, {"link": 2, "label": "object"}]},
      "tokens": [{"form": "見"}, {"form": "て"}, {"form": "い"}, {"form": "る"}]
    },
    {
      "chunk_info": {"id": 4, "links": [{"link": 3, "label": "adjectivals"}]},
      "tokens": [{"form": "女の子"}, {"form": "を"}]
    },
    {
      "chunk_info": {"id": 5, "links": [{"link": 0, "label": "source"}, {"link": 4, "label": "object"}]},
      "tokens": [{"form": "見"}, {"form": "た"}]
    }
  ]
}
`)

json_test.res
@scope("JSON") @val external parse: string => result = "parse"

こうすれば良いはずです。1
問題は、resultの型定義をどうするかです。


JSONをみていくと"result": 無名配列なので、この無名配列をarray<chunk>とします。

json_test.res
type result = { result: array<chunk> }

chunk{"chunk_info": レコード, "tokens": 無名配列}なので、レコードをchunk_info型とし、無名配列をarray<token>にします。

json_test.res
type chunk = { chunk_info: chunk_info, tokens: array<token> }

chunk_info{"id": int, "links": 無名配列}なので、この無名配列をarray<link>にします。

json_test.res
type chunk_info = { id: int, links: array<link>}

link{"link": int, "label":string}です。

json_test.res
type link = { link: int, label: string }

残りはtoken{"form": string}です。

json_test.res
type token = { form: string }

これで必要な型が定義できました。


事前に定義されていない型は、型宣言で利用できないので、末端から根に向けて宣言する感じになります。

json_test.res
type token = { form: string }
type link = { link: int, label: string }
type chunk_info = { id: int, links: array<link>}
type chunk = { chunk_info: chunk_info, tokens: array<token> }
type result = { result: array<chunk> }
@scope("JSON") @val external parse: string => result = "parse"

json_test.res
let result = parse(cotoha_result)
Console.log((result.result->Array.getUnsafe(0)).chunk_info.id)
Console.log(((result.result->Array.getUnsafe(1)).tokens->Array.getUnsafe(0)).form)

パースされ、色んな値にアクセスできるようになっています。
ReScriptでは配列に添字でアクセスするとoption<'a>が返ります。
optionの処理を一つずつ書くと煩雑になるので、Array.getUnsafeを用いました。


複雑なJSONを型定義することになったら超大変な気がします。
そもそも型付き言語でJSON使ってるのがどうなのかという話なのかも知れません。

  1. https://rescript-lang.org/docs/manual/latest/import-from-export-to-js#import-a-javascript-modules-named-export

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?