Question

I have a server that receives JSON that looks like:

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

where all the stuff is for the Server except for "result", which is to be forwarded to the client (Worker --JSON--> Server --value of "result"--> Client). Therefore, when parsing this thing with aeson, I want to keep the value of "result" as a string (or Text or whatnot), just so I can forward it to the client without caring what's inside. Problem is that "result" can be anything (array, object, etc.). So If I do

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

the decode function of aeson is going to return Nothing, since "result" is not necessarily a JSON string...

How do I tell aeson to keep parts of the JSON object as-is and just give them to me so I can do what I want with them?

Était-ce utile?

La solution

I seem to have somewhat of a solution by making the type of result be Data.Aeson.Value and then after doing a decode on the incoming JSON, I extract the result and run encode on it before forwarding it. I'm not sure if this is the best solution (because I'm not "keeping it as a string" as the question states, but decoding it then encoding it again...) but it works:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top