json 0.4.4 → 0.5
raw patch · 5 files changed
+52/−42 lines, 5 filesdep ~basedep ~sybPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, syb
API changes (from Hackage documentation)
- Text.JSON: instance MonadError String Result
+ Text.JSON: class JSKey a
+ Text.JSON: decJSDict :: (JSKey a, JSON b) => String -> JSValue -> Result [(a, b)]
+ Text.JSON: encJSDict :: (JSKey a, JSON b) => [(a, b)] -> JSValue
+ Text.JSON: fromJSKey :: JSKey a => String -> Maybe a
+ Text.JSON: instance JSKey Int
+ Text.JSON: instance JSKey JSString
+ Text.JSON: instance JSKey String
+ Text.JSON: toJSKey :: JSKey a => a -> String
- Text.JSON: class JSON a
+ Text.JSON: class JSON a where readJSONs (JSArray as) = mapM readJSON as readJSONs _ = mkError "Unable to read list" showJSONs = JSArray . map showJSON
Files
- Text/JSON.hs +48/−36
- Text/JSON/Generic.hs +0/−2
- Text/JSON/Parsec.hs +1/−1
- Text/JSON/ReadP.hs +1/−1
- json.cabal +2/−2
Text/JSON.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -XCPP -XMultiParamTypeClasses -XTypeSynonymInstances #-}+{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances #-} -------------------------------------------------------------------- -- | -- Module : Text.JSON@@ -50,19 +50,17 @@ -- ** Instance helpers , makeObj, valFromObj+ , JSKey(..), encJSDict, decJSDict ) where import Text.JSON.Types import Text.JSON.String -import Data.List import Data.Int import Data.Word-import Data.Either import Control.Monad(liftM,ap,MonadPlus(..)) import Control.Applicative-import Control.Monad.Error ( MonadError(..) ) import qualified Data.ByteString.Char8 as S import qualified Data.ByteString.Lazy.Char8 as L@@ -156,12 +154,6 @@ Ok a >>= f = f a Error x >>= _ = Error x -instance MonadError String Result where- throwError x = Error x-- catchError (Error e) h = h e- catchError x _ = x- -- | Convenient error generation mkError :: String -> Result a mkError s = Error s@@ -369,27 +361,27 @@ -- container types: -instance (Ord a, JSON a, JSON b) => JSON (M.Map a b) where #if !defined(MAP_AS_DICT)+instance (Ord a, JSON a, JSON b) => JSON (M.Map a b) where showJSON = encJSArray M.toList readJSON = decJSArray "Map" M.fromList-#else- showJSON = encJSDict M.toList- -- backwards compatibility..- readJSON a@JSArray{} = M.fromList <$> readJSON a- readJSON o = decJSDict "Map" M.fromList o-#endif instance (JSON a) => JSON (IntMap.IntMap a) where-#if !defined(MAP_AS_DICT) showJSON = encJSArray IntMap.toList readJSON = decJSArray "IntMap" IntMap.fromList+ #else-{- alternate (dict) mapping: -}- showJSON = encJSDict IntMap.toList- readJSON = decJSDict "IntMap" IntMap.fromList+instance (Ord a, JSKey a, JSON b) => JSON (M.Map a b) where+ showJSON = encJSDict . M.toList+ readJSON o = M.fromList <$> decJSDict "Map" o++instance (JSON a) => JSON (IntMap.IntMap a) where+ {- alternate (dict) mapping: -}+ showJSON = encJSDict . IntMap.toList+ readJSON o = IntMap.fromList <$> decJSDict "IntMap" o #endif + instance (Ord a, JSON a) => JSON (Set.Set a) where showJSON = encJSArray Set.toList readJSON = decJSArray "Set" Set.fromList@@ -454,22 +446,42 @@ decJSArray _ f a@JSArray{} = f <$> readJSON a decJSArray l _ _ = mkError ("readJSON{"++l++"}: unable to parse array value") -#if defined(MAP_AS_DICT)-encJSDict :: (JSON a, JSON b) => (c -> [(a,b)]) -> c -> JSValue-encJSDict f v = makeObj $ - map (\ (x,y) -> (showJSValue (showJSON x) "", showJSON y)) (f v)+-- | Haskell types that can be used as keys in JSON objects.+class JSKey a where+ toJSKey :: a -> String+ fromJSKey :: String -> Maybe a -decJSDict :: (JSON a, JSON b)+instance JSKey JSString where+ toJSKey x = fromJSString x+ fromJSKey x = Just (toJSString x)++instance JSKey Int where+ toJSKey = show+ fromJSKey key = case reads key of+ [(a,"")] -> Just a+ _ -> Nothing++-- NOTE: This prevents us from making other instances for lists but,+-- our guess is that strings are used as keys more often then other list types.+instance JSKey String where+ toJSKey = id+ fromJSKey = Just+ +-- | Encode an association list as 'JSObject' value.+encJSDict :: (JSKey a, JSON b) => [(a,b)] -> JSValue+encJSDict v = makeObj [ (toJSKey x, showJSON y) | (x,y) <- v ]++-- | Decode a 'JSObject' value into an association list.+decJSDict :: (JSKey a, JSON b) => String- -> ([(a,b)] -> c) -> JSValue- -> Result c-decJSDict _ f (JSObject o) = mapM rd (fromJSObject o) >>= return . f- where- rd (a,b) = do- pa <- decode a- pb <- readJSON b- return (pa,pb)-decJSDict l _ _ = mkError ("readJSON{"++l ++ "}: unable to read dict; expected JSON object")-#endif+ -> Result [(a,b)]+decJSDict l (JSObject o) = mapM rd (fromJSObject o)+ where rd (a,b) = case fromJSKey a of+ Just pa -> readJSON b >>= \pb -> return (pa,pb)+ Nothing -> mkError ("readJSON{" ++ l ++ "}:" +++ "unable to read dict; invalid object key")++decJSDict l _ = mkError ("readJSON{"++l ++ "}: unable to read dict; expected JSON object")+
Text/JSON/Generic.hs view
@@ -26,8 +26,6 @@ ) where import Control.Monad.State-import Control.Monad.Identity-import Data.Maybe import Text.JSON import Text.JSON.String ( runGetJSON ) import Data.Generics
Text/JSON/Parsec.hs view
@@ -109,7 +109,7 @@ (*>) = (>>) (<*) :: CharParser () a -> CharParser () b -> CharParser () a-m <* n = do x <- m; n; return x+m <* n = do x <- m; _ <- n; return x empty :: CharParser () a empty = mzero
Text/JSON/ReadP.hs view
@@ -101,7 +101,7 @@ (*>) = (>>) (<*) :: ReadP a -> ReadP b -> ReadP a-m <* n = do x <- m; n; return x+m <* n = do x <- m; _ <- n; return x empty :: ReadP a empty = pfail
json.cabal view
@@ -1,5 +1,5 @@ name: json-version: 0.4.4+version: 0.5 synopsis: Support for serialising Haskell to and from JSON description: JSON (JavaScript Object Notation) is a lightweight data-interchange@@ -90,7 +90,7 @@ if flag(split-base) if flag(generic)- build-depends: base >=4 && <5, syb+ build-depends: base >=4 && <5, syb >= 0.3.3 exposed-modules: Text.JSON.Generic Cpp-Options: -DBASE_4