composable-associations-aeson-0.1.0.1: Aeson ToJSON/FromJSON implementation for the types of composable-associations
Safe HaskellNone
LanguageHaskell2010

Data.ComposableAssociation.Aeson

Synopsis

Quickstart

Assume some example data below:

>>> data ExampleUser = ExampleUser { name :: String, age :: Int } deriving (Show, Eq, Generic)
>>> instance ToJSON ExampleUser
>>> instance FromJSON ExampleUser
>>> data ExampleUserWithMessages = ExampleUserWithMessages { name :: String, age :: Int, messages :: [Int] } deriving (Show, Eq, Generic)
>>> instance ToJSON ExampleUserWithMessages
>>> instance FromJSON ExampleUserWithMessages
>>> let aliceName = "Alice"
>>> let aliceAge = 25
>>> let messageIds = [102, 305, 410]
>>> let alice = ExampleUser aliceName aliceAge
>>> let aliceWithMessages = ExampleUserWithMessages aliceName aliceAge messageIds

Let's add those messages to the alice object without requiring our custom WithMessages version of the User type.

>>> let adHocAliceWithMessages = alice :<> (asValue messageIds :: Association "messages" [Int])
>>> encode aliceWithMessages == encode adHocAliceWithMessages
True

Since "messages" is type (not value) information, we can decode as well.

>>> decode "{\"age\":25,\"name\":\"Alice\",\"messages\":[102,305,410]}" :: Maybe (ExampleUser :<> Association "messages" [Int])
Just (ExampleUser {name = "Alice", age = 25} :<> Association Proxy [102,305,410])

In the above, Proxy is the value of type "messages".

Association Proxy a has a stand-alone encoding/decoding too

>>> encode $ Association (Proxy :: Proxy "one-off-key") [1, 2, 3]
"{\"one-off-key\":[1,2,3]}"
>>> decode "{\"one-off-key\":[1,2,3]}" :: Maybe (Association "one-off-key" [Int])
Just (Association Proxy [1,2,3])

You can build JSON objects from just values!

>>> :{
let allValues :: Association "name" String :<> Association "age" Int
    allValues = asValue aliceName :<> asValue aliceAge
in encode allValues == encode alice
:}
True

Decoding fails if you specify a non-existent key (standard Aeson behavior for failed decoding).

>>> decode "{\"one-off-key\":[1,2,3]}" :: Maybe (Association "wrong-key" [Int])
Nothing

If you try encoding with a "base" value that is itself not encoded to a JSON object you'll get a runtime exception.

>>> encode $ True :<> (asValue [1,2,3] :: Association "this-ends-poorly" [Int])
"*** Exception: JsonObjectEncodingException (Bool True)

GHC Extension Note:

  • You'll need DataKinds for this library (type level literals, no getting around this).
  • You'll probably want TypeOperators as well (although you can use WithAssociation instead of :<> to avoid this).
  • You can avoid PolyKinds if you use asValue True :: Association "key" Bool or type inference instead of Association (Proxy :: Proxy "key") True.

Re-Exported Core Types/Functions/Lens

Invalid JSON Encoding Exception

Orphan instances

(ToJSON base, ToJSON obj, KnownSymbol key) => ToJSON (base :<> Association key obj) Source #

Throws a JsonObjectEncodingException if the base value isn't encoded as a JSON object

Instance details

Methods

toJSON :: (base :<> Association key obj) -> Value #

toEncoding :: (base :<> Association key obj) -> Encoding #

toJSONList :: [base :<> Association key obj] -> Value #

toEncodingList :: [base :<> Association key obj] -> Encoding #

(FromJSON base, FromJSON obj, KnownSymbol key) => FromJSON (base :<> Association key obj) Source # 
Instance details

Methods

parseJSON :: Value -> Parser (base :<> Association key obj) #

parseJSONList :: Value -> Parser [base :<> Association key obj] #

(ToJSON obj, KnownSymbol key) => ToJSON (Association key obj) Source # 
Instance details

Methods

toJSON :: Association key obj -> Value #

toEncoding :: Association key obj -> Encoding #

toJSONList :: [Association key obj] -> Value #

toEncodingList :: [Association key obj] -> Encoding #

(FromJSON obj, KnownSymbol key) => FromJSON (Association key obj) Source # 
Instance details

Methods

parseJSON :: Value -> Parser (Association key obj) #

parseJSONList :: Value -> Parser [Association key obj] #