packages feed

unjson 0.14.1.3 → 0.15.0.0

raw patch · 4 files changed

+125/−49 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.Unjson: instance (Data.Primitive.Types.Prim a, Data.Unjson.Unjson a) => Data.Unjson.Unjson (Data.Vector.Primitive.Vector a)
- Data.Unjson: instance (Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector a, Data.Unjson.Unjson a, Data.Vector.Unboxed.Base.Unbox a) => Data.Unjson.Unjson (Data.Vector.Unboxed.Base.Vector a)
- Data.Unjson: instance (Foreign.Storable.Storable a, Data.Unjson.Unjson a) => Data.Unjson.Unjson (Data.Vector.Storable.Vector a)
- Data.Unjson: instance (GHC.Classes.Eq a, Data.Hashable.Class.Hashable a, Data.Unjson.Unjson a) => Data.Unjson.Unjson (Data.HashSet.HashSet a)
- Data.Unjson: instance (GHC.Classes.Ord a, Data.Unjson.Unjson a) => Data.Unjson.Unjson (Data.Set.Base.Set a)
- Data.Unjson: instance Data.Unjson.Unjson Data.IntSet.Base.IntSet
- Data.Unjson: instance Data.Unjson.Unjson Data.Time.Clock.UTC.UTCTime
- Data.Unjson: instance Data.Unjson.Unjson Data.Time.LocalTime.LocalTime.ZonedTime
- Data.Unjson: instance Data.Unjson.Unjson a => Data.Unjson.Unjson (Data.IntMap.Base.IntMap a)
- Data.Unjson: instance Data.Unjson.Unjson a => Data.Unjson.Unjson (Data.Vector.Vector a)
- Data.Unjson: instance Data.Unjson.Unjson a => Data.Unjson.Unjson [a]
- Data.Unjson: instance Data.Unjson.Unjson v => Data.Unjson.Unjson (Data.HashMap.Base.HashMap Data.Text.Internal.Lazy.Text v)
- Data.Unjson: instance Data.Unjson.Unjson v => Data.Unjson.Unjson (Data.HashMap.Base.HashMap Data.Text.Internal.Text v)
- Data.Unjson: instance Data.Unjson.Unjson v => Data.Unjson.Unjson (Data.HashMap.Base.HashMap GHC.Base.String v)
- Data.Unjson: instance Data.Unjson.Unjson v => Data.Unjson.Unjson (Data.Map.Base.Map Data.Text.Internal.Lazy.Text v)
- Data.Unjson: instance Data.Unjson.Unjson v => Data.Unjson.Unjson (Data.Map.Base.Map Data.Text.Internal.Text v)
- Data.Unjson: instance Data.Unjson.Unjson v => Data.Unjson.Unjson (Data.Map.Base.Map GHC.Base.String v)
+ Data.Unjson: enumUnjsonDef :: forall a. (Eq a, Typeable a, Enum a, Bounded a, Data a) => UnjsonDef a
+ Data.Unjson: instance (Data.Primitive.Types.Prim a, Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.Vector.Primitive.Vector a)
+ Data.Unjson: instance (Data.Typeable.Internal.Typeable v, Data.Unjson.Unjson v) => Data.Unjson.Unjson (Data.HashMap.Base.HashMap Data.Text.Internal.Lazy.Text v)
+ Data.Unjson: instance (Data.Typeable.Internal.Typeable v, Data.Unjson.Unjson v) => Data.Unjson.Unjson (Data.HashMap.Base.HashMap Data.Text.Internal.Text v)
+ Data.Unjson: instance (Data.Typeable.Internal.Typeable v, Data.Unjson.Unjson v) => Data.Unjson.Unjson (Data.HashMap.Base.HashMap GHC.Base.String v)
+ Data.Unjson: instance (Data.Typeable.Internal.Typeable v, Data.Unjson.Unjson v) => Data.Unjson.Unjson (Data.Map.Internal.Map Data.Text.Internal.Lazy.Text v)
+ Data.Unjson: instance (Data.Typeable.Internal.Typeable v, Data.Unjson.Unjson v) => Data.Unjson.Unjson (Data.Map.Internal.Map Data.Text.Internal.Text v)
+ Data.Unjson: instance (Data.Typeable.Internal.Typeable v, Data.Unjson.Unjson v) => Data.Unjson.Unjson (Data.Map.Internal.Map GHC.Base.String v)
+ Data.Unjson: instance (Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.IntMap.Internal.IntMap a)
+ Data.Unjson: instance (Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.Vector.Vector a)
+ Data.Unjson: instance (Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson [a]
+ Data.Unjson: instance (Data.Vector.Generic.Base.Vector Data.Vector.Unboxed.Base.Vector a, Data.Unjson.Unjson a, Data.Vector.Unboxed.Base.Unbox a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.Vector.Unboxed.Base.Vector a)
+ Data.Unjson: instance (Foreign.Storable.Storable a, Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.Vector.Storable.Vector a)
+ Data.Unjson: instance (GHC.Classes.Eq a, Data.Hashable.Class.Hashable a, Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.HashSet.HashSet a)
+ Data.Unjson: instance (GHC.Classes.Ord a, Data.Unjson.Unjson a, Data.Typeable.Internal.Typeable a) => Data.Unjson.Unjson (Data.Set.Internal.Set a)
+ Data.Unjson: instance Data.Unjson.Unjson Data.IntSet.Internal.IntSet
+ Data.Unjson: instance Data.Unjson.Unjson Data.Time.Clock.Internal.UTCTime.UTCTime
+ Data.Unjson: instance Data.Unjson.Unjson Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
- Data.Unjson: [ArrayUnjsonDef] :: Maybe (PrimaryKeyExtraction k) -> ArrayMode -> ([k] -> Result v) -> (v -> [k]) -> UnjsonDef k -> UnjsonDef v
+ Data.Unjson: [ArrayUnjsonDef] :: Typeable k => Maybe (PrimaryKeyExtraction k) -> ArrayMode -> ([k] -> Result v) -> (v -> [k]) -> UnjsonDef k -> UnjsonDef v
- Data.Unjson: [FieldDefDef] :: Text -> Text -> a -> (s -> a) -> UnjsonDef a -> FieldDef s a
+ Data.Unjson: [FieldDefDef] :: Typeable a => Text -> Text -> a -> (s -> a) -> UnjsonDef a -> FieldDef s a
- Data.Unjson: [FieldOptDef] :: Text -> Text -> (s -> Maybe a) -> UnjsonDef a -> FieldDef s (Maybe a)
+ Data.Unjson: [FieldOptDef] :: Typeable a => Text -> Text -> (s -> Maybe a) -> UnjsonDef a -> FieldDef s (Maybe a)
- Data.Unjson: [FieldRODef] :: Text -> Text -> (s -> a) -> UnjsonDef a -> FieldDef s ()
+ Data.Unjson: [FieldRODef] :: Typeable a => Text -> Text -> (s -> a) -> UnjsonDef a -> FieldDef s ()
- Data.Unjson: [FieldReqDef] :: Text -> Text -> (s -> a) -> UnjsonDef a -> FieldDef s a
+ Data.Unjson: [FieldReqDef] :: Typeable a => Text -> Text -> (s -> a) -> UnjsonDef a -> FieldDef s a
- Data.Unjson: [MapUnjsonDef] :: UnjsonDef k -> (HashMap Text k -> Result v) -> (v -> HashMap Text k) -> UnjsonDef v
+ Data.Unjson: [MapUnjsonDef] :: Typeable k => UnjsonDef k -> (HashMap Text k -> Result v) -> (v -> HashMap Text k) -> UnjsonDef v
- Data.Unjson: arrayOf :: UnjsonDef a -> UnjsonDef [a]
+ Data.Unjson: arrayOf :: Typeable a => UnjsonDef a -> UnjsonDef [a]
- Data.Unjson: arrayWithModeAndPrimaryKeyOf :: (Ord pk) => ArrayMode -> (a -> pk) -> UnjsonDef pk -> UnjsonDef a -> UnjsonDef [a]
+ Data.Unjson: arrayWithModeAndPrimaryKeyOf :: (Ord pk, Typeable a) => ArrayMode -> (a -> pk) -> UnjsonDef pk -> UnjsonDef a -> UnjsonDef [a]
- Data.Unjson: arrayWithModeOf :: ArrayMode -> UnjsonDef a -> UnjsonDef [a]
+ Data.Unjson: arrayWithModeOf :: Typeable a => ArrayMode -> UnjsonDef a -> UnjsonDef [a]
- Data.Unjson: arrayWithPrimaryKeyOf :: (Ord pk) => (a -> pk) -> UnjsonDef pk -> UnjsonDef a -> UnjsonDef [a]
+ Data.Unjson: arrayWithPrimaryKeyOf :: (Ord pk, Typeable a) => (a -> pk) -> UnjsonDef pk -> UnjsonDef a -> UnjsonDef [a]
- Data.Unjson: field :: (Unjson a) => Text -> (s -> a) -> Text -> Ap (FieldDef s) a
+ Data.Unjson: field :: (Unjson a, Typeable a) => Text -> (s -> a) -> Text -> Ap (FieldDef s) a
- Data.Unjson: fieldBy :: Text -> (s -> a) -> Text -> UnjsonDef a -> Ap (FieldDef s) a
+ Data.Unjson: fieldBy :: Typeable a => Text -> (s -> a) -> Text -> UnjsonDef a -> Ap (FieldDef s) a
- Data.Unjson: fieldDef :: (Unjson a) => Text -> a -> (s -> a) -> Text -> Ap (FieldDef s) a
+ Data.Unjson: fieldDef :: (Unjson a, Typeable a) => Text -> a -> (s -> a) -> Text -> Ap (FieldDef s) a
- Data.Unjson: fieldDefBy :: Text -> a -> (s -> a) -> Text -> UnjsonDef a -> Ap (FieldDef s) a
+ Data.Unjson: fieldDefBy :: Typeable a => Text -> a -> (s -> a) -> Text -> UnjsonDef a -> Ap (FieldDef s) a
- Data.Unjson: fieldOpt :: (Unjson a) => Text -> (s -> Maybe a) -> Text -> Ap (FieldDef s) (Maybe a)
+ Data.Unjson: fieldOpt :: (Unjson a, Typeable a) => Text -> (s -> Maybe a) -> Text -> Ap (FieldDef s) (Maybe a)
- Data.Unjson: fieldOptBy :: Text -> (s -> Maybe a) -> Text -> UnjsonDef a -> Ap (FieldDef s) (Maybe a)
+ Data.Unjson: fieldOptBy :: Typeable a => Text -> (s -> Maybe a) -> Text -> UnjsonDef a -> Ap (FieldDef s) (Maybe a)
- Data.Unjson: fieldReadonly :: (Unjson a) => Text -> (s -> a) -> Text -> Ap (FieldDef s) ()
+ Data.Unjson: fieldReadonly :: (Unjson a, Typeable a) => Text -> (s -> a) -> Text -> Ap (FieldDef s) ()
- Data.Unjson: fieldReadonlyBy :: Text -> (s -> a) -> Text -> UnjsonDef a -> Ap (FieldDef s) ()
+ Data.Unjson: fieldReadonlyBy :: Typeable a => Text -> (s -> a) -> Text -> UnjsonDef a -> Ap (FieldDef s) ()
- Data.Unjson: mapOf :: UnjsonDef x -> UnjsonDef (HashMap Text x)
+ Data.Unjson: mapOf :: Typeable x => UnjsonDef x -> UnjsonDef (HashMap Text x)

Files

+ CHANGELOG.md view
@@ -0,0 +1,6 @@+# unjson-0.15.0.0 (2018-02-22)+* Breaking change: Unjson definitions now require the underlying types+  to have Typeable instances ([#6](https://github.com/scrive/unjson/pull/6)).+* Added a way to automatically derive Unjson definitions for+  parameterless sum types (`enumUnjsonDef`) ([#7](https://github.com/scrive/unjson/pull/7)).+* Dropped support for GHC < 7.8.
src/Data/Unjson.hs view
@@ -122,6 +122,7 @@ -- ** Maps, enums, sums , mapOf , enumOf+, enumUnjsonDef , disjointUnionOf , unionOf -- ** Helpers@@ -317,7 +318,7 @@   -- 'UnjsonDef'.   unjsonDef :: UnjsonDef a -instance {-# OVERLAPPABLE #-} (Unjson a) => Unjson [a] where+instance {-# OVERLAPPABLE #-} (Unjson a, Typeable a) => Unjson [a] where   unjsonDef = arrayOf unjsonDef  instance {-# INCOHERENT #-} Unjson String where@@ -364,44 +365,44 @@ instance (Unjson a, Unjson b) => Unjson (Either a b)  where unjsonDef = unjsonAeson -} -instance Unjson a => Unjson (IntMap.IntMap a)+instance (Unjson a, Typeable a) => Unjson (IntMap.IntMap a)   where unjsonDef = invmap IntMap.fromList IntMap.toList unjsonDef-instance (Ord a, Unjson a) => Unjson (Set.Set a)+instance (Ord a, Unjson a, Typeable a) => Unjson (Set.Set a)   where unjsonDef = invmap Set.fromList Set.toList unjsonDef-instance (Eq a, Hashable a, Unjson a) => Unjson (HashSet.HashSet a)+instance (Eq a, Hashable a, Unjson a, Typeable a) => Unjson (HashSet.HashSet a)   where unjsonDef = invmap HashSet.fromList HashSet.toList unjsonDef-instance Unjson a => Unjson (Vector.Vector a)+instance (Unjson a, Typeable a) => Unjson (Vector.Vector a)   where unjsonDef = invmap Vector.fromList Vector.toList unjsonDef-instance (Data.Vector.Generic.Vector Data.Vector.Unboxed.Vector a, Unjson a, Data.Vector.Unboxed.Unbox a) => Unjson (Data.Vector.Unboxed.Vector a)+instance (Data.Vector.Generic.Vector Data.Vector.Unboxed.Vector a, Unjson a, Data.Vector.Unboxed.Unbox a, Typeable a) => Unjson (Data.Vector.Unboxed.Vector a)   where unjsonDef = invmap Data.Vector.Unboxed.fromList Data.Vector.Unboxed.toList unjsonDef-instance (Storable a, Unjson a) => Unjson (Data.Vector.Storable.Vector a)+instance (Storable a, Unjson a, Typeable a) => Unjson (Data.Vector.Storable.Vector a)   where unjsonDef = invmap Data.Vector.Storable.fromList Data.Vector.Storable.toList unjsonDef-instance (Prim a, Unjson a) => Unjson (Data.Vector.Primitive.Vector a)+instance (Prim a, Unjson a, Typeable a) => Unjson (Data.Vector.Primitive.Vector a)   where unjsonDef = invmap Data.Vector.Primitive.fromList Data.Vector.Primitive.toList unjsonDef   mapFst :: (a -> c) -> (a,b) -> (c,b) mapFst f (a,b) = (f a, b) -instance Unjson v => Unjson (Map.Map String v)+instance (Typeable v, Unjson v) => Unjson (Map.Map String v)   where unjsonDef = invmap (Map.fromList . map (mapFst Text.unpack) . HashMap.toList)                                      (HashMap.fromList . map (mapFst Text.pack) . Map.toList)                                      unjsonDef-instance Unjson v => Unjson (Map.Map Text.Text v)+instance (Typeable v, Unjson v) => Unjson (Map.Map Text.Text v)   where unjsonDef = invmap (Map.fromList . HashMap.toList)                                      (HashMap.fromList . Map.toList)                                      unjsonDef-instance Unjson v => Unjson (Map.Map LazyText.Text v)+instance (Typeable v, Unjson v) => Unjson (Map.Map LazyText.Text v)   where unjsonDef = invmap (Map.fromList . map (mapFst LazyText.fromStrict) . HashMap.toList)                                      (HashMap.fromList . map (mapFst LazyText.toStrict) . Map.toList)                                      unjsonDef-instance Unjson v => Unjson (HashMap.HashMap String v)+instance (Typeable v, Unjson v) => Unjson (HashMap.HashMap String v)   where unjsonDef = invmap (HashMap.fromList . map (mapFst Text.unpack) . HashMap.toList)                                      (HashMap.fromList . map (mapFst Text.pack) . HashMap.toList)                                      unjsonDef-instance Unjson v => Unjson (HashMap.HashMap Text.Text v)+instance (Typeable v, Unjson v) => Unjson (HashMap.HashMap Text.Text v)   where unjsonDef = MapUnjsonDef unjsonDef pure id-instance Unjson v => Unjson (HashMap.HashMap LazyText.Text v)+instance (Typeable v, Unjson v) => Unjson (HashMap.HashMap LazyText.Text v)   where unjsonDef = invmap (HashMap.fromList . map (mapFst LazyText.fromStrict) . HashMap.toList)                                      (HashMap.fromList . map (mapFst LazyText.toStrict) . HashMap.toList)                                      unjsonDef@@ -590,12 +591,12 @@ -- | Opaque 'UnjsonDef' defines a bidirectional JSON parser. data UnjsonDef a where   SimpleUnjsonDef   :: Text.Text -> (Aeson.Value -> Result k) -> (k -> Aeson.Value) -> UnjsonDef k-  ArrayUnjsonDef    :: Maybe (PrimaryKeyExtraction k) -> ArrayMode -> ([k] -> Result v) -> (v -> [k]) -> UnjsonDef k -> UnjsonDef v+  ArrayUnjsonDef    :: Typeable k => Maybe (PrimaryKeyExtraction k) -> ArrayMode -> ([k] -> Result v) -> (v -> [k]) -> UnjsonDef k -> UnjsonDef v   ObjectUnjsonDef   :: Ap (FieldDef k) (Result k) -> UnjsonDef k   TupleUnjsonDef    :: Ap (TupleFieldDef k) (Result k) -> UnjsonDef k   DisjointUnjsonDef :: Text.Text -> [(Text.Text, k -> Bool, Ap (FieldDef k) (Result k))] -> UnjsonDef k   UnionUnjsonDef    :: [(k -> Bool, Ap (FieldDef k) (Result k))] -> UnjsonDef k-  MapUnjsonDef      :: UnjsonDef k -> (HashMap.HashMap Text.Text k -> Result v) -> (v -> HashMap.HashMap Text.Text k) -> UnjsonDef v+  MapUnjsonDef      :: Typeable k => UnjsonDef k -> (HashMap.HashMap Text.Text k -> Result v) -> (v -> HashMap.HashMap Text.Text k) -> UnjsonDef v  instance Invariant UnjsonDef where   invmap f g (SimpleUnjsonDef name p s) = SimpleUnjsonDef name (fmap f . p) (s . g)@@ -634,10 +635,10 @@ -- parsing definition.  'FieldDef' has three cases for fields that are -- required, optional (via 'Maybe') or jave default value. data FieldDef s a where-  FieldReqDef :: Text.Text -> Text.Text -> (s -> a) -> UnjsonDef a -> FieldDef s a-  FieldOptDef :: Text.Text -> Text.Text -> (s -> Maybe a) -> UnjsonDef a -> FieldDef s (Maybe a)-  FieldDefDef :: Text.Text -> Text.Text -> a -> (s -> a) -> UnjsonDef a -> FieldDef s a-  FieldRODef  :: Text.Text -> Text.Text -> (s -> a) -> UnjsonDef a -> FieldDef s ()+  FieldReqDef :: Typeable a => Text.Text -> Text.Text -> (s -> a)       -> UnjsonDef a -> FieldDef s a+  FieldOptDef :: Typeable a => Text.Text -> Text.Text -> (s -> Maybe a) -> UnjsonDef a -> FieldDef s (Maybe a)+  FieldDefDef :: Typeable a => Text.Text -> Text.Text -> a -> (s -> a)  -> UnjsonDef a -> FieldDef s a+  FieldRODef  :: Typeable a => Text.Text -> Text.Text -> (s -> a)       -> UnjsonDef a -> FieldDef s ()  -- | Define a tuple element. 'TupleFieldDef' holds information about -- index, accessor function and a parser definition.@@ -1021,7 +1022,7 @@ -- > -- > data Thing = Thing { thingCredentials :: Credentials, ... } -- > unjsonCredentials :: UnjsonDef Credentials-fieldBy :: Text.Text -> (s -> a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) a+fieldBy :: Typeable a => Text.Text -> (s -> a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) a fieldBy key f docstring valuedef = liftAp (FieldReqDef key docstring f valuedef)  -- | Declare a required field with definition from 'Unjson' typeclass.@@ -1036,7 +1037,7 @@ -- > -- > data Thing = Thing { thingCredentials :: Credentials, ... } -- > instance Unjson Credentials where ...-field :: (Unjson a) => Text.Text -> (s -> a) -> Text.Text -> Ap (FieldDef s) a+field :: (Unjson a, Typeable a) => Text.Text -> (s -> a) -> Text.Text -> Ap (FieldDef s) a field key f docstring = fieldBy key f docstring unjsonDef  -- | Declare an optional field and definition by valuedef.@@ -1052,7 +1053,7 @@ -- > -- > data Thing = Thing { thingCredentials :: Credentials, ... } -- > unjsonCredentials :: UnjsonDef Credentials-fieldOptBy :: Text.Text -> (s -> Maybe a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) (Maybe a)+fieldOptBy :: Typeable a => Text.Text -> (s -> Maybe a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) (Maybe a) fieldOptBy key f docstring valuedef = liftAp (FieldOptDef key docstring f valuedef)  -- | Declare an optional field and definition by 'Unjson' typeclass.@@ -1067,7 +1068,7 @@ -- > -- > data Thing = Thing { thingCredentials :: Credentials, ... } -- > instance Unjson Credentials where ...-fieldOpt :: (Unjson a) => Text.Text -> (s -> Maybe a) -> Text.Text -> Ap (FieldDef s) (Maybe a)+fieldOpt :: (Unjson a, Typeable a) => Text.Text -> (s -> Maybe a) -> Text.Text -> Ap (FieldDef s) (Maybe a) fieldOpt key f docstring = fieldOptBy key f docstring unjsonDef  -- | Declare a field with default value and definition by valuedef.@@ -1083,7 +1084,7 @@ -- > -- > data Thing = Thing { thingCredentials :: Credentials, ... } -- > unjsonCredentials :: UnjsonDef Credentials-fieldDefBy :: Text.Text -> a -> (s -> a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) a+fieldDefBy :: Typeable a => Text.Text -> a -> (s -> a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) a fieldDefBy key def f docstring valuedef = liftAp (FieldDefDef key docstring def f valuedef)  -- | Declare a field with default value and definition by 'Unjson' typeclass.@@ -1097,7 +1098,7 @@ -- >          "Port to listen on, defaults to 80" -- > -- > data Thing = Thing { thingPort :: Int, ... }-fieldDef :: (Unjson a) => Text.Text -> a -> (s -> a) -> Text.Text -> Ap (FieldDef s) a+fieldDef :: (Unjson a, Typeable a) => Text.Text -> a -> (s -> a) -> Text.Text -> Ap (FieldDef s) a fieldDef key def f docstring = fieldDefBy key def f docstring unjsonDef  @@ -1116,7 +1117,7 @@ -- >          "Additional string" -- > -- > data Thing = Thing { thingPort :: Int, thingString :: String, ... }-fieldReadonly :: (Unjson a) => Text.Text -> (s -> a) -> Text.Text ->  Ap (FieldDef s) ()+fieldReadonly :: (Unjson a, Typeable a) => Text.Text -> (s -> a) -> Text.Text ->  Ap (FieldDef s) () fieldReadonly key f docstring = fieldReadonlyBy key f docstring unjsonDef  -- | Declare a field that is readonly from the point of view of Haskell structures,@@ -1136,7 +1137,7 @@ -- >          "Additional string" -- > -- > data Thing = Thing { thingPort :: Port, thingString :: String, ... }-fieldReadonlyBy ::  Text.Text -> (s -> a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) ()+fieldReadonlyBy :: Typeable a => Text.Text -> (s -> a) -> Text.Text -> UnjsonDef a -> Ap (FieldDef s) () fieldReadonlyBy key f docstring valuedef = liftAp (FieldRODef key docstring f valuedef)  -- | Declare an object as bidirectional mapping from JSON object to Haskell record and back.@@ -1173,7 +1174,7 @@ -- > objectOf $ pure X -- >   <*> field "xmap" xMap -- >       "Map string to Y value"-mapOf :: UnjsonDef x -> UnjsonDef (LazyHashMap.HashMap Text.Text x)+mapOf :: Typeable x => UnjsonDef x -> UnjsonDef (LazyHashMap.HashMap Text.Text x) mapOf def = MapUnjsonDef def pure id  -- | Provide sum type support. Bidirectional case matching in Haskell@@ -1237,7 +1238,7 @@ unionOf alternates =   UnionUnjsonDef (map (\(b,c) -> (b,fmap return c)) alternates) --- | Provide sum type support for parametersless constructors.+-- | Provide sum type support for parameterless constructors. -- -- For related functionality see 'disjointUnionOf'. --@@ -1253,6 +1254,24 @@ enumOf key alternates =   DisjointUnjsonDef key (map (\(a,b) -> (a,(==)b,fmap return (pure b))) alternates) +-- | Automatic sum type conversion with parameterless constructors.+--+-- Basically an automatic version of 'enumOf'.+--+-- Example:+--+-- > data X = A | B deriving (Eq, Data, Enum, Bounded)+-- >+-- > instance Unjson X where unjsonDef = enumUnjsonDef+--+enumUnjsonDef+  :: forall a. (Eq a, Typeable a, Enum a, Bounded a, Data a)+  => UnjsonDef a+enumUnjsonDef = enumOf typeName [ (Text.pack $ show $ toConstr c, c) | c <- constructors ]+  where+    typeName = Text.pack . show . typeRep $ (Proxy :: Proxy a)+    constructors = enumFromTo minBound maxBound :: [a]+ -- | Declare array of values where each of them is described by -- valuedef. Use 'unjsonAeson' to parse. --@@ -1263,7 +1282,7 @@ -- > -- > unjsonThing :: UnjsonDef Thing -- > unjsonThing = ...-arrayOf :: UnjsonDef a -> UnjsonDef [a]+arrayOf :: Typeable a => UnjsonDef a -> UnjsonDef [a] arrayOf = arrayWithModeOf ArrayModeStrict  -- | Declare array of values where each of them is described by@@ -1276,7 +1295,7 @@ -- > -- > unjsonThing :: UnjsonDef Thing -- > unjsonThing = ...-arrayWithModeOf :: ArrayMode -> UnjsonDef a -> UnjsonDef [a]+arrayWithModeOf :: Typeable a => ArrayMode -> UnjsonDef a -> UnjsonDef [a] arrayWithModeOf mode valuedef = ArrayUnjsonDef Nothing mode pure id valuedef  -- | Declare array of primitive values lifed from 'Aeson'. Accepts@@ -1308,7 +1327,7 @@ -- >                              (objectOf $ pure (,) -- >                                 <*> field "key" fst "Key in mapping" -- >                                 <*> field "value" fst "Value in mapping")-arrayWithModeAndPrimaryKeyOf :: (Ord pk)+arrayWithModeAndPrimaryKeyOf :: (Ord pk, Typeable a)                              => ArrayMode                              -> (a -> pk)                              -> UnjsonDef pk@@ -1349,7 +1368,7 @@ -- >                              (objectOf $ pure (,) -- >                                 <*> field "key" fst "Key in mapping" -- >                                 <*> field "value" fst "Value in mapping")-arrayWithPrimaryKeyOf :: (Ord pk)+arrayWithPrimaryKeyOf :: (Ord pk, Typeable a)                       => (a -> pk)                       -> UnjsonDef pk                       -> UnjsonDef a
test/Test.hs view
@@ -4,6 +4,7 @@  import qualified Data.Text as Text import qualified Data.ByteString.Lazy.Char8 as BSL+import Data.Int import Data.Typeable import Data.Unjson import Control.Applicative@@ -36,6 +37,7 @@             , konfigComment     :: Maybe Text.Text             , konfigOptions     :: [Text.Text]             , konfigAlternates  :: Maybe (Text.Text,Credentials)+            , konfigInt32       :: Int32             }   deriving (Eq,Ord,Show,Typeable) @@ -68,6 +70,9 @@            <*> fieldOpt "alternates"                  konfigAlternates                  "Alternate names for this server"+           <*> field "int32"+                 konfigInt32+                 "A bounded integer fieldd."  unjsonCredentials :: UnjsonDef Credentials unjsonCredentials = objectOf $ pure Credentials@@ -95,6 +100,7 @@                    [ "username" .= "usr1"                    , "password" .= "pass1"                    ]+               , "int32" .= 42                ]   let expect = Konfig                { konfigHostname = "www.example.com"@@ -103,6 +109,7 @@                , konfigCredentials = Credentials "usr1" "pass1" Nothing                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32 = 42                }    let Result val iss = parse unjsonKonfig json@@ -136,6 +143,7 @@               , "credentials" .= Aeson.object                                 [ "username" .= "usr1"                                 ]+              , "int32" .= 999               ]   let json = Aeson.object                [ "payload" .= json1@@ -166,6 +174,7 @@                    [ "username" .= "usr1"                    ]                , "credentials" .= "www.example.com"+               , "int32" .= 999                ]    let Result val iss = parse unjsonKonfig json@@ -220,6 +229,7 @@                , konfigCredentials = Credentials "usr1" "pass1" Nothing                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32 = 42                }    let json = unjsonToJSON unjsonKonfig expect@@ -237,6 +247,7 @@                , konfigCredentials = Credentials "usr1" "pass1" Nothing                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32 = 42                }    let jsonstr = BSL.unpack $ unjsonToByteStringLazy' (Options { nulls = False, indent = 4, pretty = True }) unjsonKonfig konfig@@ -249,7 +260,8 @@         , "        \"password\": \"pass1\""         , "    },"         , "    \"comment\": \"nice server\","-        , "    \"options\": []"+        , "    \"options\": [],"+        , "    \"int32\": 42"         , "}"         ]   assertEqual "Serialize pretty prints proper indents" expect jsonstr@@ -263,7 +275,8 @@         , "          \"password\": \"pass1\""         , "     },"         , "     \"comment\": \"nice server\","-        , "     \"options\": []"+        , "     \"options\": [],"+        , "     \"int32\": 42"         , "}"         ]   assertEqual "Serialize pretty prints proper indents" expect5 jsonstr5@@ -277,7 +290,8 @@         , "\"password\":\"pass1\""         , "},"         , "\"comment\":\"nice server\","-        , "\"options\":[]"+        , "\"options\":[],"+        , "\"int32\":42"         , "}"         ]   assertEqual "Serialize pretty prints proper indents" expect3 jsonstr3@@ -292,6 +306,7 @@                , konfigCredentials = Credentials "usr1" "pass1" Nothing                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32 = 42                }    let jsonstr = BSL.unpack $ unjsonToByteStringLazy' (Options { nulls = True, indent = 4, pretty = True }) unjsonKonfig konfig@@ -306,7 +321,8 @@         , "    },"         , "    \"comment\": \"nice server\","         , "    \"options\": [],"-        , "    \"alternates\": null"+        , "    \"alternates\": null,"+        , "    \"int32\": 42"         , "}"         ]   assertEqual "Serialize pretty prints proper indents" expect jsonstr@@ -388,16 +404,15 @@     assertBool "Documentation generates" (length docstr > 0)   return () + data AB = A | B    deriving (Show, Eq, Ord) - unjsonEnumAB :: UnjsonDef AB unjsonEnumAB = enumOf "mode"                      [ ("A", A)                      , ("B", B)] - test_enum_field :: Test test_enum_field = "test_enum_field" ~: do   do@@ -421,6 +436,37 @@     let Result val iss = parse unjsonEnumAB json     assertEqual "No problems" [Anchored (Path [PathElemKey "mode"]) "value 'wrong' is not one of the allowed for enumeration [A,B]"] iss ++data AutoAB = AutoA | AutoB+   deriving (Show, Eq, Ord, Enum, Bounded, Data, Typeable)++unjsonAutoEnumAB :: UnjsonDef AutoAB+unjsonAutoEnumAB = enumUnjsonDef++test_auto_enum_field :: Test+test_auto_enum_field = "test_auto_enum_field" ~: do+  do+    let json = Aeson.object+                 [ "AutoAB" .= "AutoA"+                 ]+    let Result val iss = parse unjsonAutoEnumAB json+    assertEqual "No problems" [] iss+    assertEqual "Proper value present" AutoA val+  do+    let json = Aeson.object+                 [ "AutoAB" .= "AutoB"+                 ]+    let Result val iss = parse unjsonAutoEnumAB json+    assertEqual "No problems" [] iss+    assertEqual "Proper value present" AutoB val+  do+    let json = Aeson.object+                 [ "AutoAB" .= "wrong"+                 ]+    let Result val iss = parse unjsonAutoEnumAB json+    assertEqual "No problems" [Anchored (Path [PathElemKey "AutoAB"]) "value 'wrong' is not one of the allowed for enumeration [AutoA,AutoB]"] iss+    + test_update_from_serialization :: Test test_update_from_serialization = "test_update_from_serialization" ~: do   let initial = Konfig@@ -430,6 +476,7 @@                , konfigCredentials = Credentials "usr1" "pass1" Nothing                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32   = 42                }   let expect = Konfig                { konfigHostname = "www.example.com"@@ -438,6 +485,7 @@                , konfigCredentials = Credentials "usr2" "pass1" (Just "domain")                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32   = 256                }    let json = Aeson.object@@ -447,6 +495,7 @@                , "credentials" .= Aeson.object                                [ "domain" .= "domain"                                , "username" .= "usr2" ]+               , "int32" .= 256                ]   let Result val iss = update initial unjsonKonfig json   assertEqual "No problems" [] iss@@ -462,6 +511,7 @@                , konfigCredentials = Credentials "usr1" "pass1" (Just "domain")                , konfigAlternates = Nothing                , konfigOptions = []+               , konfigInt32 = 0                }   let expect = Konfig                { konfigHostname = "www.example.com"@@ -470,6 +520,7 @@                , konfigCredentials = Credentials "usr1" "pass1" (Nothing)                , konfigAlternates = Just ("abc", Credentials "usrx" "passx" Nothing)                , konfigOptions = []+               , konfigInt32 = 256                }    let json = Aeson.object@@ -486,7 +537,7 @@                                  ]                ]   let Result _ iss = update initial unjsonKonfig json-  assertEqual "Cannot reset mangatory field without default"+  assertEqual "Cannot reset mandatory field without default"                 [Anchored (Path [PathElemKey "hostname"]) "expected Text, encountered Null"] iss   return () @@ -600,12 +651,12 @@                ]       jsonEmbedded = Aeson.object                      [ "a_map" .= json ]-  let unjsonMapByInstance :: (Unjson a) => UnjsonDef a+  let unjsonMapByInstance :: (Unjson a, Typeable a) => UnjsonDef a       unjsonMapByInstance = objectOf $ pure id          <*> field "a_map"              id              "The only map"-  let unjsonMapByExplicit :: (Unjson a) => UnjsonDef (HashMap.HashMap Text.Text a)+  let unjsonMapByExplicit :: (Unjson a, Typeable a) => UnjsonDef (HashMap.HashMap Text.Text a)       unjsonMapByExplicit = objectOf $ pure id          <*> fieldBy "a_map"              id
unjson.cabal view
@@ -1,5 +1,5 @@ name:                unjson-version:             0.14.1.3+version:             0.15.0.0 synopsis:            Bidirectional JSON parsing and generation. description:         Bidirectional JSON parsing and generation                      with automatic documentation support.@@ -13,10 +13,10 @@ copyright:           Scrive AB category:            Data build-type:          Simple-extra-source-files:  README.md+extra-source-files:  README.md, CHANGELOG.md cabal-version:       >=1.18-tested-with:         GHC == 7.4.2,  GHC == 7.6.3, GHC == 7.8.4,-                     GHC == 7.10.3, GHC == 8.0.1+tested-with:         GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2,+                     GHC == 8.2.2  source-repository head   type:     git@@ -25,13 +25,13 @@ source-repository this   type:     git   location: https://github.com/scrive/unjson.git-  tag:      0.14.1.3+  tag:      0.15.0.0  library   exposed-modules:     Data.Unjson   -- other-modules:   -- other-extensions:-  build-depends:       base >= 4.5 && < 5, text, aeson >= 1.0 && < 1.3,+  build-depends:       base >= 4.7 && < 5, text, aeson >= 1.0 && < 1.3,                        free, scientific, attoparsec,                        unordered-containers, vector, pretty,                        bytestring >= 0.10, containers, hashable,