2016-11-06 18 views
0

でJSONの日付データ用のカスタムインスタンスを書く:は、私は次の形式でJSONの日付データを持っているアイソーン

{"date": "2015-04-12"} 

と対応するHaskellのタイプ:

data Date = Date { 
     year :: Int 
    , month :: Int 
    , day :: Int 
    } 

どのように私は、カスタムFromJSONを書くことができますし、 AesonライブラリのToJSONの機能ですか? インスタンスの派生は、書式設定のために機能しません。

答えて

1

あなたはなぜ車輪の再発明/文字列から

{-# LANGUAGE OverloadedStrings #-} 
{-# OPTIONS_GHC -fno-warn-tabs #-} 

import Control.Monad 
import Data.Aeson 
import qualified Data.Text as T 
import Text.Read (readMaybe) 
-- import qualified Data.Attoparsec.Text as A 

data Date = Date Int Int Int deriving (Read, Show) 

instance ToJSON Date where 
    toJSON (Date y m d) = toJSON $ object [ 
     "date" .= T.pack (str 4 y ++ "-" ++ str 2 m ++ "-" ++ str 2 d)] 
     where 
      str n = pad . show where 
       pad s = replicate (n - length s) '0' ++ s 

instance FromJSON Date where 
    parseJSON = withObject "date" $ \v -> do 
     str <- v .: "date" 
     let 
      [email protected](~[y, m, d]) = T.split (== '-') str 
     guard (length ps == 3) 
     Date <$> readNum y <*> readNum m <*> readNum d 
     where 
      readNum = maybe (fail "not num") return . readMaybe . T.unpack 

    -- -- or with attoparsec 
    -- parseJSON = withObject "date" $ \v -> do 
    -- str <- v .: "date" 
    -- [y, m, d] <- either fail return $ 
    --  A.parseOnly (A.decimal `A.sepBy` A.char '-') str 
    -- return $ Date y m d 
5

にY/M/D変換がありますか? timeパッケージにはDateと呼ばれるものの準標準表現があります。これはDayと呼ばれています。それはより良くなる:同じパッケージでも、あなたが持っているフォーマットからDayをパースするためのユーティリティを提供するだけでなく、これらのユーティリティはaesonにエクスポートさえさえなります。あなたが本当には日、月、年を抽出したい場合は

ghci> :set -XOverloadedStrings 
ghci> import Data.Time.Calendar 
ghci> import Data.Aeson 
ghci> fromJSON "2015-04-12" :: Result Day 
Success 2015-04-12 
ghci> toJSON (fromGregorian 2015 4 12) 
String "2015-04-12" 

、あなたは常にtoGregorian :: Day -> (Integer, Int, Int)を使用することができます:うん、DayためaesonToJSONFromJSONインスタンスが既に存在しています。標準的な抽象化に固執することは、おそらく長期的には良い選択です。

関連する問題