LoginSignup
5
1

More than 5 years have passed since last update.

purescript-simple-jsonで型が不定なJSONをマッピングする

Posted at

purescript-simple-jsonは神。


稀によく、こういうAPIを見かけます。

{
  "name": "json1",
  "result_type": "intarray", // result_typeとかいう謎カラムで
  "result": [ 1, 2, 3 ] // resultの型が変化する!!!
}
{
  "name": "json2",
  "result_type": "boolean",
  "result": true // 今度はboolだ……
}
{
  "name": "json3",
  "result_type": "mydata", // mydataとは……?
  "result": { // objectだってあるぞ!!
    "name": "myname",
    "value": "abcdef"
  }
}

()

こういうのをうまいことマッピングしたいんですけど、どうすればいいんでしょうかね。

型を考える

まずは、各resultに対応する型を定義しちゃいましょう!

data Result
  = IntArray (Array Int) -- コンストラクタ名は適当
  | BoolValue Boolean
  | MyData { name :: String, value :: String }

そして、最終的にほしいデータ型を作ります。

-- 実際にほしいのはこの型
type Response' = { name :: String, result :: Result } -- Resultが直和型だったらresult_typeは不要ですよね!

-- newtypeでラップする必要があるのでこうする
newtype Response = Response Response'

最後に、生Jsonに対応する型にも名前を付けちゃいましょう。

type ResponseJSON =
  { name :: String
  , result_type :: String
  , result :: Foreign -- resultは`Foreign`型で受ける!
  }

準備は整いました!

ReadForeignのインスタンスにしちゃおう

purescript-simple-jsonがプロパティを読むためには、レコードのメンバがReadForeignのインスタンスであればいいです。ということは、

instance readForeignResponse :: ReadForeign Response where
  readImpl o = do
    { name, result, result_type } :: ResponseJSON <- readImpl o
    Response <<< { name, result: _ } <$> case result_type of
      "intarray" -> pure <<< IntArray =<< readImpl result
      "boolean" -> pure <<< BoolValue =<< readImpl result
      "mydata" -> pure <<< MyData =<< readImpl result
      other -> fail <<< ForeignError $ "cannot read result_type: " <> other

ハイ終わり!!!!

読める……読めるぞ!!

main :: Effect Unit
main = do
  case readJSON json of
    Left error -> traverse1_ logShow error
    Right (Response { name, result }) -> do
      logShow name
      case result of
        IntArray arr -> logShow arr -- [ 1, 2, 3 ]
        BoolValue b -> logShow b -- true
        MyData d -> logShow d -- { name: "myname", value: "abcdef" }

おわり

  • purescript-simple-jsonは神
  • jsonで型が一つに定まってなくてもどういうデータが来るのか分かってればマッピングできる
  • justin-san(@kimagure)拝み倒していく
  • PureScriptめっちゃいい言語
5
1
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
1