2013-07-15 5 views
2

У меня есть сервер, который получает JSON, который выглядит как:Как сохранить неединичные части JSON в виде строк с помощью aeson?

{ "foo": "bar", "bono": "bobo", 
    "result": { "some": ["complex", "JSON", "structure",... 
} 

, где все вещи для сервера кроме для «результата», который должен быть направлен клиенту (работник --JSON- -> Сервер - значение «результат» -> Клиент). Поэтому, анализируя эту вещь с помощью aeson, я хочу сохранить значение «результат» как строку (или текст или что-то еще), чтобы я мог переслать ее клиенту, не заботясь о том, что внутри. Проблема в том, что «результат» может быть любым (массив, объект и т. Д.). Так что если я

data RPCResult = RPCResult { foo :: Text, result :: Text } 

decode функция эсон собирается вернуться Nothing, так как «результат» не обязательно является строка JSON ...

Как я говорю эсон держать детали из JSON-объект как есть и просто отдать их мне, чтобы я мог делать то, что хочу с ними?

ответ

3

я, кажется, несколько из раствора, делая вид result быть Data.Aeson.Value, а затем после выполнения decode на входящем JSON, я извлечь result и запустить encode на него, прежде чем направить его. Я не уверен, что это лучшее решение (потому что я не «держу его в виде строки», как говорится в вопросе, но декодирует его, затем кодирует его снова ...), но он работает:

import Data.Aeson 
import Data.Maybe 
import Data.ByteString.Lazy (fromStrict, ByteString) 
import Data.ByteString.UTF8 (fromString) 
import Control.Applicative 

data RPCResult = RPCResult { foo :: Text, result :: Value } 

instance FromJSON RPCResult where 
    parseJSON (Object v) = RPCResult <$> v .: "foo" <*> v .: "result" 

-- example just so you get the idea: 
toRPCResult :: String -> RPCResult 
toRPCResult = fromJust . decode . fromStrict . fromString 

getResult :: String -> ByteString 
getResult = encode . result . toRPCResult