我的 ToJSON Base64 实例正常吗? FromJSON 实例会是什么样子?
Is my ToJSON Base64 instance sane? What would FromJSON instance look like?
我正在尝试将 Base64 编码为 JSON。我遇到了 this 对话。我注意到 snoyberg 已经在 FP Complete 代码库中包含了 Base64
newtype
,所以我想我会试一试。
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as B64
newtype Base64 = Base64 { toByteString :: B.ByteString }
deriving ( Eq, Ord, Show,IsString)
ToJSON
实例看起来很简单。我将不胜感激。
instance ToJSON Base64 where
toJSON (Base64 bs) =
toJSON $ B.unpack $ B64.decodeLenient bs
FromJSON 实例是我 运行 遇到问题的地方。
研究其他示例,我推测我必须使用 withArray
,它需要 (Array -> Parser a)
。这就是我卡住的地方。
parseBase64 :: Array -> Parser
parseBase64 (Array a) = ...
我在这里尝试了很多方法,我对这里需要发生什么感到困惑,或者即使我在正确的轨道上。如果我能得到一些像 "you're on the right track keep going" 这样简单的反馈,或者被指向不同的方向,那将不胜感激。
-- | 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
returns),您可以这样做,并在 Base64
:
中有一个 encoded 字节串
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'
我正在尝试将 Base64 编码为 JSON。我遇到了 this 对话。我注意到 snoyberg 已经在 FP Complete 代码库中包含了 Base64
newtype
,所以我想我会试一试。
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as B64
newtype Base64 = Base64 { toByteString :: B.ByteString }
deriving ( Eq, Ord, Show,IsString)
ToJSON
实例看起来很简单。我将不胜感激。
instance ToJSON Base64 where toJSON (Base64 bs) =
toJSON $ B.unpack $ B64.decodeLenient bs
FromJSON 实例是我 运行 遇到问题的地方。
研究其他示例,我推测我必须使用 withArray
,它需要 (Array -> Parser a)
。这就是我卡住的地方。
parseBase64 :: Array -> Parser
parseBase64 (Array a) = ...
我在这里尝试了很多方法,我对这里需要发生什么感到困惑,或者即使我在正确的轨道上。如果我能得到一些像 "you're on the right track keep going" 这样简单的反馈,或者被指向不同的方向,那将不胜感激。
-- | 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
returns),您可以这样做,并在 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'