このコードは、再帰的な JSON 構造を、私が作成した haskell オブジェクトに解析します。Aeson ライブラリを使用しています。私が直面している問題は、再帰呼び出しでも簡単にエラー チェックを実行できるようにしたいということです。現在、エラーが発生するたびにダミー値 (ayyLmao) を使用しています。しかし、私は Parser モナドから取得したエラー チェックを活用したいと考えています。どうすればこれを行うことができ、プロセス内のコードをクリーンアップできますか? 必要に応じて、サンプル JSON を投稿することもできます。
編集: "ayyLmao" (したがって、愚かな名前) を取り除き、代わりにエラー チェック用の Parser モナドに 'mzero' を使用したいことを指摘したいと思います。
type Comments = Vector Comment
data Comment = Comment
{ author :: Text
, body :: Text
, replies :: Comments
} deriving Show
-- empty placeholder value (only should appear when errors occur)
ayyLmao :: Comment
ayyLmao = Comment "Ayy" "Lmao" V.empty
parseComment :: Object -> Maybe Comments
parseComment obj = flip parseMaybe obj $ \listing -> do
-- go through intermediate objects
comments <- listing .: "data" >>= (.: "children")
-- parse every comment in an array
return $ flip fmap comments $ \commentData -> case commentData of
-- if the data in the array is an object, parse the comment
-- (using a dummy value on error)
Object v -> fromMaybe ayyLmao (parseMaybe parseComment' v)
-- use a dummy value for errors (we should only get objects in
-- the array
_ -> ayyLmao
where
parseComment' :: Object -> Parser Comment
parseComment' v = do
-- get all data from the object
comment <- v .: "data"
authorField <- comment .: "author"
bodyField <- comment .: "body"
replyObjs <- comment .: "replies"
return $ case replyObjs of
-- if there are more objects, then parse recursively
Object more -> case parseComment more of
-- errors use the dummy value again
Just childReplies -> Comment authorField bodyField childReplies
Nothing -> ayyLmao
-- otherwise, we've reached the last comment in the
-- tree
_ -> Comment authorField bodyField V.empty
編集:以下の回答のコードは正しいですが、変更したソリューションを追加したいと思います。与えられた解決策では、"null" はこれ以上応答がないことを示していると想定していますが、何らかの理由で API 設計者はそれを空の文字列で表す必要があると判断しました。
instance FromJSON Comment where
parseJSON = withObject "Comment" $ \obj -> do
dat <- obj .: "data"
commReplies <- dat .: "replies"
Comment
<$> dat .: "author"
<*> dat .: "body"
<*> case commReplies of
Object _ -> getComments <$> dat .: "replies"
String "" -> return V.empty
_ -> fail "Expected more comments or a the empty string"