composable-associations-aeson 0.1.0.0 → 0.1.0.1
raw patch · 4 files changed
+33/−29 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.ComposableAssociation.Aeson: instance GHC.Exception.Exception Data.ComposableAssociation.Aeson.JsonObjectEncodingException
+ Data.ComposableAssociation.Aeson: instance GHC.Exception.Type.Exception Data.ComposableAssociation.Aeson.JsonObjectEncodingException
Files
- composable-associations-aeson.cabal +1/−1
- doctest/Main.hs +1/−1
- src/Data/ComposableAssociation/Aeson.hs +16/−25
- test/Main.hs +15/−2
composable-associations-aeson.cabal view
@@ -1,5 +1,5 @@ name: composable-associations-aeson-version: 0.1.0.0+version: 0.1.0.1 synopsis: Aeson ToJSON/FromJSON implementation for the types of composable-associations description: This library provides the orphan instances implementation JSON serialization for the types in
doctest/Main.hs view
@@ -4,5 +4,5 @@ import Test.DocTest main :: IO ()-main = doctest [ "-XOverloadedStrings", "-XDeriveGeneric", "-XDataKinds", "-XTypeOperators",+main = doctest [ "-XOverloadedStrings", "-XDeriveGeneric", "-XDataKinds", "-XTypeOperators", "-isrc", "src/Data/ComposableAssociation/Aeson.hs" ]
src/Data/ComposableAssociation/Aeson.hs view
@@ -75,21 +75,23 @@ -- >>> 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\"}"+-- >>> 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]--- >>> encode messageIds--- "[102,305,410]"+-- >>> let alice = ExampleUser aliceName aliceAge+-- >>> let aliceWithMessages = ExampleUserWithMessages aliceName aliceAge messageIds ----- 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]}"+-- 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])@@ -105,23 +107,14 @@ -- >>> 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+-- let allValues :: Association "name" String :<> Association "age" Int+-- allValues = asValue aliceName :<> asValue aliceAge+-- in encode allValues == encode alice -- :}--- "{\"a-bool\":true,\"an-alice\":{\"age\":25,\"name\":\"Alice\"},\"a-string\":\"Hello\"}"+-- True -- -- Decoding fails if you specify a non-existent key (standard Aeson behavior for failed decoding). --@@ -132,8 +125,6 @@ -- -- >>> 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: --
test/Main.hs view
@@ -11,6 +11,7 @@ import Data.Proxy import Data.Aeson+import Data.Aeson.Types import Data.ByteString.Lazy import Test.Tasty import Test.Tasty.QuickCheck@@ -47,7 +48,7 @@ [ testCase "Association ToJSON Instance" $ encode testUser1FriendsAssoc @?= "{\"message_ids\":[1,2,3]}" , testCase "Association FromJSON Instance" $ decode "{\"message_ids\":[1,2,3]}" @?= Just testUser1FriendsAssoc , testCase ":<> ToJSON" $- encode (testUser1 :<> testUser1FriendsAssoc) @?= "{\"message_ids\":[1,2,3],\"userId\":1,\"name\":\"Sam\"}"+ encode (testUser1 :<> testUser1FriendsAssoc) @?= encode testUser1WithMessages , testCase ":<> FromJSON" $ decode "{\"message_ids\":[1,2,3],\"userId\":1,\"name\":\"Sam\"}" @?= Just (testUser1 :<> testUser1FriendsAssoc) , testCase ":<> Invalid Encoding1" $ do@@ -60,7 +61,7 @@ , testCase "Decode Association Null" $ decode "{\"message_ids\":null}" @?= Just testMissingMessages , testCase "Decode Association Missing Key" $ decode "{}" @?= Just testMissingMessages , testCase "Encode :<> Missing Association" $- encode (testUser1 :<> testMissingMessages) @?= "{\"message_ids\":null,\"userId\":1,\"name\":\"Sam\"}"+ encode (testUser1 :<> testMissingMessages) @?= encode testUser1WithMessages { withmessages_message_ids = Nothing } , testCase "Decode :<> Missing Association" $ decode "{\"message_ids\":null,\"userId\":1,\"name\":\"Sam\"}" @?= Just (testUser1 :<> testMissingMessages) , testCase "Decode :<> Missing Association Key" $@@ -75,8 +76,20 @@ instance ToJSON TestUser instance FromJSON TestUser +data TestUserWithMessages = TestUserWithMessages { withMessages_userId :: Int+ , withMessages_name :: String + , withmessages_message_ids :: Maybe [Int]}+ deriving (Show, Eq, Generic)+instance ToJSON TestUserWithMessages where+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = Prelude.drop 13 }+instance FromJSON TestUserWithMessages where+ parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = Prelude.drop 13 }+ testUser1 :: TestUser testUser1 = TestUser { userId = 1, name = "Sam" }++testUser1WithMessages :: TestUserWithMessages+testUser1WithMessages = TestUserWithMessages 1 "Sam" (Just [1, 2, 3]) testUser1FriendsAssoc :: Association "message_ids" [Int] testUser1FriendsAssoc = Association Proxy [1, 2, 3]