2016-01-30 19 views
0

我想將Base64編碼爲JSON。我碰到了this對話。我注意到snoyberg已經在FP Complete代碼庫中包含了Base64newtype,所以我想我會試試看。我的ToJSON Base64實例是否理智? FromJSON實例會是什麼樣子?

進口合格Data.ByteString爲B

進口合格Data.ByteString.Base64如B64

NEWTYPE的Base64 = Base64的{toByteString :: B.ByteString}
導出(式,奧德展,IsString)

ToJSON實例似乎很簡單。我會很感激一個理智的檢查。

實例的toJSON的Base64其中 的toJSON(Base64編碼BS)=
的toJSON $ B.unpack $ B64.decodeLenient BS

的FromJSON實例是我遇到的問題。

學習其他示例我推測我必須使用withArray,它需要(Array -> Parser a)。這是我卡住的地方。

parseBase64 ::陣列 - >解析器

parseBase64(陣列A)= ...

我在這裏嘗試了很多方法,我很困惑,需要做些什麼在這裏或者即使我在正確的軌道上。如果我能得到一些簡單的反饋信息,比如「你在正確的軌道上繼續前進」,或者被指向不同的方向,那將是值得讚賞的。

回答

2

我以前做過這個練習:https://github.com/futurice/haskell-base64-bytestring-type/blob/0a1176d16c71c219fe113bc3f130f64d8dda47bc/src/Data/ByteString/Base64/Type.hs#L46-L51

-- | Get base64 encoded bytestring 
getEncodedByteString64 :: ByteString64 -> ByteString 
getEncodedByteString64 = Base64.encode . getByteString64 

instance ToJSON ByteString64 where 
    toJSON = toJSON . decodeLatin1 . getEncodedByteString64 

instance FromJSON ByteString64 where 
    parseJSON = withText "ByteString" $ 
     pure . ByteString64 . decodeLenient . encodeUtf8 

細看之後,看來你編碼ByteString(任意)爲 'Word8' 的陣列,(這是什麼BS.unpack收益)爲你可以做,並在Base64編碼字節字符串:

instance ToJSON Base64 where 
    toJSON = toJSON . B.unpack . B64.decodeLenient . toByteString 

instance FromJSON Base64 where 
    parseJSON = fmap (Base64 . B64.encode . B.pack) . parseJSON 

這樣喲你不必擔心[Word8]是如何編碼的,只要它被一致解碼即可。

如果你喜歡手工處理數組,那麼它看起來像:

instance FromJSON Base64 where 
    parseJSON (Array a) = do 
     a' <- traverse parseJSON a -- :: Parser (V.Vector Word8) 
     return $ Base64 . B64.encode . B.pack . V.toList $ a' 
    parseJSON _ = fail "Array expected" 

instance FromJSON Base64 where 
    parseJSON = withArray "Base64" $ \a -> do 
     a' <- traverse parseJSON a -- :: Parser (V.Vector Word8) 
     return $ Base64 . B64.encode . B.pack . V.toList $ a'