module Data.JSON2.Query
(
JFilter
, isStr, isStrBy
, isNum, isNumBy
, isBool, isTrue, isFalse
, isNull, isAtomic
, isObj
, getFromObj, getFromKey
, getFromKeys, getFromKeyBy
, isArr
, getFromArr, getFromIndex
, getFromIndexes, getFromIndexBy
, getChildern
, (>>>), (<+>)
, orElse, when, guards
, deep, deepObj, deepArr
)
where
import qualified Data.Map as M (empty, singleton, unionWith,
filterWithKey, elems, union, lookup)
import qualified Data.Maybe as Mb (catMaybes)
import qualified Data.List as L (nub)
import Data.JSON2.Types
type JFilter = Json -> Jsons
infixl 1 >>>
infixr 2 <+>
isObj :: JFilter
isObj (JObject o) = [JObject o]
isObj _ = []
isArr :: JFilter
isArr (JArray a) = [JArray a]
isArr _ = []
isStr :: JFilter
isStr (JString s) = [JString s]
isStr _ = []
isStrBy :: (String -> Bool) -> JFilter
isStrBy p (JString s) = if p s then [JString s] else []
isStrBy _ _ = []
isNum :: JFilter
isNum (JNumber n) = [JNumber n]
isNum _ = []
isNumBy :: Fractional a => (a -> Bool) -> JFilter
isNumBy p (JNumber n) = if p (fromRational n) then [JNumber n] else []
isNumBy _ _ = []
isBool :: JFilter
isBool (JBool p) = [JBool p]
isBool _ = []
isTrue :: JFilter
isTrue (JBool True) = [JBool True]
isTrue _ = []
isFalse :: JFilter
isFalse (JBool False) = [JBool False]
isFalse _ = []
isNull :: JFilter
isNull JNull = [JNull]
isNull _ = []
isAtomic :: JFilter
isAtomic (JString s) = [JString s]
isAtomic (JNumber n) = [JNumber n]
isAtomic (JBool p) = [JBool p]
isAtomic JNull = [JNull]
isAtomic _ = []
getFromKey :: String -> JFilter
getFromKey k (JObject m) = Mb.catMaybes [(M.lookup k m)]
getFromKey _ _ = []
getFromKeys :: [String] -> JFilter
getFromKeys ks (JObject m) = Mb.catMaybes $ map (\k -> (M.lookup k m)) (L.nub ks)
getFromKeys _ _ = []
getFromKeyBy :: (String -> Bool) -> JFilter
getFromKeyBy f (JObject m) = M.elems $ M.filterWithKey (\k _ -> f k) m
getFromKeyBy _ _ = []
getFromObj :: JFilter
getFromObj (JObject o) = M.elems o
getFromObj _ = []
getFromArr :: JFilter
getFromArr (JArray a) = a
getFromArr _ = []
getFromIndex :: Int -> JFilter
getFromIndex i (JArray a) = [a !! i | i <length a]
getFromIndex _ _ = []
getFromIndexes :: [Int] -> JFilter
getFromIndexes is ja = concat [getFromIndex i ja | i <- is]
getFromIndexBy :: (Int -> Bool) -> JFilter
getFromIndexBy f (JArray xs) = [y| (y,k) <- [(x,i) | x <- xs | i <- [0..]], f k]
getFromIndexBy _ _ = []
getChildern :: JFilter
getChildern (JObject o) = M.elems o
getChildern (JArray a) = a
getChildern _ = []
(>>>) :: JFilter -> JFilter -> JFilter
(f >>> g) t = concat [g t' | t' <- f t]
(<+>) :: JFilter -> JFilter -> JFilter
(f <+> g) t = f t ++ g t
orElse :: JFilter -> JFilter -> JFilter
orElse f g t
| null res1 = g t
| otherwise = res1
where res1 = f t
when :: JFilter -> JFilter -> JFilter
when f g t
| null (g t) = [t]
| otherwise = f t
guards :: JFilter -> JFilter -> JFilter
guards f g t
| null (f t) = []
| otherwise = g t
deep :: JFilter -> JFilter
deep f = f `orElse` (getChildern >>> deep f)
deepObj :: JFilter -> JFilter
deepObj f = f `orElse` (getFromObj >>> deepObj f)
deepArr :: JFilter -> JFilter
deepArr f = f `orElse` (getFromArr >>> deepArr f)