2016-01-30 4 views
0

Я пытаюсь кодировать Base64 в JSON. Я столкнулся с диалогом this. Я заметил, что snoyberg уже включил Base64newtype в кодовую базу FP Complete, поэтому я решил попробовать.Является ли мой экземпляр ToJSON Base64 разумным? Как выглядит экземпляр FromJSON?

импорта квалифицированы как В Data.ByteString

импорт квалифицированных Data.ByteString.Base64 как В64

Newtype Base64 = Base64 {toByteString :: B.ByteString}
выводе (уравнение, Ord, Show, IsString)

ToJSON экземпляр казался достаточно простым. Я был бы признателен за проверку здравомыслия.

экземпляр ToJSON Base64, где toJSON (Base64 шс) =
toJSON $ B.unpack $ B64.decodeLenient шс

Экземпляр FromJSON где я столкнуться с проблемами.

Изучение других примеров Предполагаю, что я должен использовать withArray, который хочет (Array -> Parser a). Здесь я застреваю.

parseBase64 :: Array -> Parser

parseBase64 (Array а) = ...

Я пробовал много подходов здесь, я запутался, что должно произойти здесь, или даже если я на правильном пути вообще. Если бы я мог получить некоторую обратную связь так же просто, как «вы на правильном пути, продолжайте идти» или укажете в другом направлении, это будет оценено по достоинству.

ответ

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'