composable-associations-aeson-0.1.0.0: Aeson ToJSON/FromJSON implementation for the types of composable-associations

Safe HaskellNone
LanguageHaskell2010

Data.ComposableAssociation.Aeson

Contents

Synopsis

Quickstart

Assume some example data below:

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

Let's add those messages to the user JSON object without bothering to define another type.

>>> let aliceWithMessages = alice :<> (asValue messageIds :: Association "messages" [Int])
>>> encode aliceWithMessages
"{\"age\":25,\"name\":\"Alice\",\"messages\":[102,305,410]}"

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])

These are chainable too!

>>> :{
let manyAssociations :: ExampleUser :<> Association "numbers" [Int] :<> Association "bools" [Bool]
    manyAssociations = alice :<> asValue [1,2,3] :<> asValue [True, False]
in encode manyAssociations
:}
"{\"age\":25,\"name\":\"Alice\",\"bools\":[true,false],\"numbers\":[1,2,3]}"

You can build JSON objects from just values!

>>> :{
let allValues :: Association "a-bool" Bool :<> Association "a-string" String :<> Association "an-alice" ExampleUser
    allValues = asValue True :<> asValue "Hello" :<> asValue alice
in encode allValues
:}
"{\"a-bool\":true,\"an-alice\":{\"age\":25,\"name\":\"Alice\"},\"a-string\":\"Hello\"}"

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)
>>> encode $ [1,2,3] :<> (asValue "will not work" :: Association "still" String)
"*** Exception: JsonObjectEncodingException (Array [Number 1.0,Number 2.0,Number 3.0])

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 Symbol key obj)) Source #

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

Methods

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

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

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

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

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

Methods

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

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

(ToJSON obj, KnownSymbol key) => ToJSON (Association Symbol key obj) Source # 
(FromJSON obj, KnownSymbol key) => FromJSON (Association Symbol key obj) Source #