Da Sie für ein Beispiel auf Base64-kodiert Ihre Daten gefragt über JSON zu schicken, habe ich ein grobes Beispiel peitschte:
{-# LANGUAGE OverloadedStrings #-}
module Main(main) where
import qualified Control.Applicative as App
import qualified Data.Aeson as A
import Data.Aeson.Types
import Data.ByteString
import qualified Data.ByteString.Lazy as LB
import Data.ByteString.Base64
import Data.Maybe (fromMaybe)
import Data.Text
import Data.Text.Encoding
data MyObject = MyObject { objectName :: Text, objectData :: ByteString } deriving (Eq)
instance FromJSON ByteString where
parseJSON (String t) = pure $ (either (const "") id . decode . encodeUtf8) t
parseJSON _ = App.empty
instance ToJSON ByteString where
toJSON = String . decodeUtf8 . encode
instance FromJSON MyObject where
parseJSON (Object v) = MyObject <$> v .: "name" <*> v .: "data"
parseJSON _ = App.empty
instance ToJSON MyObject where
toJSON obj = object [ "name" .= objectName obj, "data" .= objectData obj ]
exampleObject :: MyObject
exampleObject = MyObject "example" "\x01\x02\x03\x04\x05"
exampleJson :: LB.ByteString
exampleJson = "{\"data\":\"AQIDBAU=\",\"name\":\"example\"}"
main :: IO()
main = do
print $ A.encode exampleObject
print $ exampleObject == fromMaybe (MyObject "fail" "") (A.decode exampleJson)
Welche sollte die folgende Ausgabe erzeugen:
"{\"data\":\"AQIDBAU=\",\"name\":\"example\"}"
True
Um ein wenig expliziter zu sein, passiert die wahre Magie in unseren Definitionen von ToJSON
und FromJSON
für ByteString
:
instance FromJSON ByteString where
parseJSON (String t) = pure $ (either (const "") id . decode . encodeUtf8) t
parseJSON _ = App.empty
instance ToJSON ByteString where
toJSON = String . decodeUtf8 . encode
Kurz gesagt, dies bietet Aeson-Richtung, wie wir wollen, dass es jede Instanz des (strengen) ByteString
Typs serialisiert. Jetzt wird jede gefundene Instanz von ByteString
automatisch codiert und dekodiert, wie wir angegeben haben (beachten Sie, wie MyObject
wie eine "typische" Aeson-Definition aussieht). Natürlich, wenn Sie nur insbesondereByteString
s codieren möchten, könnten Sie die instance
Definitionen verzichten und es direkt dort in den Code für MyObject
Serialisierung tun.
Die ToJSON
ruft einfach die encode
aus der Base64-Bibliothek auf dem Eingang und wandelt die resultierenden ByteString
(aus dem encode
Aufruf) zu einem Text
Objekt, das die Eingabe des String
Konstruktor (eine Art von Aeson Value
, die zurückgegeben werden müssen, von dieser Funktion).
Die FromJSON
sieht etwas gruseliger aus, aber - im Prinzip - ist ziemlich ähnlich. Wir nehmen die Aeson Value
vom Typ String
(für alles andere geben wir empty
zurück) und wir konvertieren den Wert, der im String
Objekt enthalten ist, in ByteString
. Wir geben dann diese ByteString
an die base64 decode
-Methode, die eine Either
produziert (je nachdem, ob es die ByteString
erfolgreich dekodieren konnte oder nicht). Wir geben einfach eine leere Zeichenfolge zurück, falls dies fehlgeschlagen ist, andernfalls geben wir den decodierten Wert für das Objekt an.
Die Hauptfunktion dient als einfache Plausibilitätsprüfung. Ich kodiere zuerst exampleObject
(enthält einen 5-Byte-Binärstring) und drucke seinen Wert. In der folgenden Zeile nehmen wir diese Ausgabe und haben sie exampleJson
genannt. Wir dekodieren exampleJson
und vergleichen es mit dem Speicher, den wir im Speicher erstellt hatten.Diese Werte sind - wie erwartet - einander gleich, sodass Sie sehen können, dass das Codieren und Decodieren ordnungsgemäß funktioniert.
Im Allgemeinen ist binary nicht mit JSON kompatibel (dh Ihre Binärdaten könnten Ihren JSON durch Hinzufügen von abgrenzenden Zeichen wie '' ',' '' '' '' '') beschädigen. Sie sollten einen Algorithmus in Betracht ziehen B. [base64] (https://hackage.haskell.org/package/base64-bytestring), um zuerst Ihre Binärdatei in ein ASCII-Format zu konvertieren, wenn Sie diese Daten über ein Nur-Text-Format (z. B. JSON) übertragen möchten. – RageD
@RageD, wenn es ein einfaches Beispiel gibt, wie man das mit Aeson macht, wird das sehr hilfreich sein.Sie könnten es als eine Antwort verwenden. Ich schätze, man könnte es über den Draht als 'Text' und in' senden Aeson-Dekodierer, wandle zuerst 'Text' in' ByteString' mit 'encodeUTF8' um und dann' decide' in 'base64', um originale Binärdaten zurück zu bekommen. Nicht sicher, ob ich das richtig verstanden habe. – Sal