我的ToJSON Base64实例是否理智? FromJSON实例会是什么样的?

时间:2016-01-30 21:03:46

标签: json haskell base64 bytestring

我正在尝试将Base64编码为JSON。我遇到了this对话。我注意到snoyberg已经将Base64 newtype包含在FP完整代码库中,所以我想我会尝试一下。

  

将限定的Data.ByteString导入为B

     

将限定的Data.ByteString.Base64导入为B64

     

newtype Base64 = Base64 {toByteString :: B.ByteString}
     派生(Eq,Ord,Show,IsString)

ToJSON实例似乎很简单。我很感激理智。

  

实例ToJSON Base64在哪里      toJSON(Base64 bs)=
       toJSON $ B.unpack $ B64.decodeLenient bs

FromJSON实例是我遇到问题的地方。

研究其他我猜测的例子我必须使用想要withArray的{​​{1}}。这就是我被卡住的地方。

  

parseBase64 :: Array - >解析器

     

parseBase64(Array a)= ...

我在这里尝试了很多方法,我很困惑这里需要发生什么,或者即使我在正确的轨道上也是如此。如果我能得到一些简单的反馈,如“你在正确的轨道上继续前进”,或指向不同的方向,那将是值得赞赏的。

1 个答案:

答案 0 :(得分: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'