hjson-query (empty) → 0.4
raw patch · 5 files changed
+393/−0 lines, 5 filesdep +basedep +containersdep +hjsonsetup-changed
Dependencies added: base, containers, hjson
Files
- LICENSE +31/−0
- Setup.hs +6/−0
- examples/Example1.hs +56/−0
- hjson-query.cabal +29/−0
- src/Text/HJson/Query.hs +271/−0
+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) 2010, Yuriy Iskra+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * The names of its contributors may not be used to endorse or + promote products derived from this software without specific prior + written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ examples/Example1.hs view
@@ -0,0 +1,56 @@+import Text.HJson hiding (toString)+import Text.HJson.Query+import Text.HJson.Pretty as PP ++-- parse JSON+jParse :: String -> Json+jParse jstr = case (fromString jstr) of+ Left l -> error l+ Right json -> json++j0 = jParse "{}"+j1 = jParse "{\"Europa\": {\"Ukraine\": [\"Kiyv\", \"Gitomir\", \"Lviv\"]}}"+j2 = jParse "{\"Asia\": {\"Japan\": [\"Tokyo\"]}}"+j3 = jParse "{\"Europa\": {\"UnitedKingdom\": [\"London\", \"Glasgow\"]}}"+j4 = jParse "{\"Europa\": {\"Germany\": [\"Berlin\", \"Bonn\"]}}"+j5 = jParse "{\"Africa\": {}}"+j6 = jParse"{\"America\": {\"USA\": [], \"Canada\": [\"Toronto\"]}}"+j7 = jParse "{\"Australia\": [\"Melburn\", \"Adelaida\"]}"+merg = jMergesRec [j0, j1, j2, j3, j4, j5, j6, j7]+ex0 = putStrLn $ toString " " merg+---------------------------------------------------------------------------++pprint js = mapM_ putStrLn $ map (toString " ") js --pretty print ++query1 = getFromKeys ["Europa", "America", "Africa"] +json1 = query1 merg +ex1 = pprint json1+---------------------------------------------------------------------------+record1 = fromString "[\"Sidoroff\",\"Jhon\",1975,null]"+ex11 = getFromIndexes [3,1,0] `fmap` record1++---------------------------------------------------------------------------++query2 = query1 >>> getFromObj +json2 = query2 merg+ex2 = pprint json2+---------------------------------------------------------------------------++-- Qwery: All citys Europa, America, Australia and Africa+q31 = getFromKeys ["Europa", "America", "Africa", "Australia"] + >>> (getFromArr `orElse` getFromObj)+ >>> (isStr `orElse` getFromArr)+ex31 = pprint $ q31 merg++q32 = getFromKeys ["Europa", "America", "Africa", "Australia"] + >>> (getFromObj `when` isObj)+ >>> getFromArr+ex32 = pprint $ q32 merg++q33 = getFromKeys ["Europa", "America", "Africa", "Australia"] + >>> + deep getFromArr+ex33 = pprint $ q33 merg++----------------------------------------------------------------------------+ex4 = debug (deep isPrimitive) "[1,[false, true, [null]]]"
+ hjson-query.cabal view
@@ -0,0 +1,29 @@+Name: hjson-query+Version: 0.4+Synopsis: library for querying from JSON+Category: Text+Description: library(HXT-like) for querying from JSON+License: BSD3+License-file: LICENSE+Author: YuriyIskra <iskra.yw@gmail.com>+Maintainer: YuriyIskra <iskra.yw@gmail.com>+Stability: Experimental+Copyright: Copyright (c) 2010 Yuriy Iskra+Build-type: Simple+Cabal-version: >= 1.6++extra-source-files:+ examples/Example1.hs++library+ Exposed-modules: Text.HJson.Query+ + Build-Depends: hjson, + base >= 4 && < 5,+ containers >= 0.2 && < 1+ + hs-source-dirs: src++Source-repository head+ Type: git+ Location: git://github.com/iskra/hjson-query.git
+ src/Text/HJson/Query.hs view
@@ -0,0 +1,271 @@+module Text.HJson.Query where+import qualified Data.Map as M (empty, unionWith, elems, union, lookup)+import qualified Data.Maybe as Mb (catMaybes)+import qualified Data.List as L (nub)+import qualified Text.HJson.Pretty as PP (toString)+import Text.HJson++type Jsons = [Json]+type JFilter = Json -> Jsons++infixl 1 >>>+infixr 2 <+>++--------------------------------------------------------------------------++-- | create empty JSON object+jEmpty :: Json+jEmpty = JObject (M.empty)++-- | merge two JSON Objects+jMerge :: Json -> Json -> Json+jMerge (JObject x ) (JObject y) = JObject $ M.union x y+jMerge _ _ = jEmpty+++-- | recursive merge two JSON Objects+jMergeRec :: Json -> Json -> Json+jMergeRec (JObject x) (JObject y) = JObject $ M.unionWith (\m n -> jMergeRec m n) x y+jMmergeRec _ _ = jEmpty++-- | merge list JSON Objects+jMerges :: [Json] -> Json+jMerges [] = jEmpty+jMerges js = foldl1 jMerge js++-- | recursive merge lists JSON Objects+--+-- Example:+--+-- > import Text.HJson hiding (toString)+-- > import Text.HJson.Query+-- > import Text.HJson.Pretty+-- > +-- > -- Parse JSON+-- > jParse :: String -> Json+-- > jParse jstr = case (fromString jstr) of+-- > Left l -> error l+-- > Right json -> json+-- > +-- > j0 = jParse "{}"+-- > j1 = jParse "{\"Europa\": {\"Ukraine\": [\"Kiyv\", \"Gitomir\", \"Lviv\"]}}"+-- > j2 = jParse "{\"Asia\": {\"Japan\": [\"Tokyo\"]}}"+-- > j3 = jParse "{\"Europa\": {\"UnitedKingdom\": [\"London\", \"Glasgow\"]}}"+-- > j4 = jParse "{\"Europa\": {\"Germany\": [\"Berlin\", \"Bonn\"]}}"+-- > j5 = jParse "{\"Africa\": {}}"+-- > j6 = jParse"{\"America\": {\"USA\": [], \"Canada\": [\"Toronto\"]}}"+-- > j7 = jParse "{\"Australia\": [\"Melburn\", \"Adelaida\"]}"+-- > merg = jMergesRec [j0, j1, j2, j3, j4, j5, j6, j7]+-- > ex0 = putStrLn $ toString " " merg+--+-- Result:+--+-- >{+-- > "Africa": {+-- > },+-- > "America": {+-- > "Canada": ["Toronto"],+-- > "USA": []+-- > },+-- > "Asia": {+-- > "Japan": ["Tokyo"]+-- > },+-- > "Australia": ["Melburn", "Adelaida"],+-- > "Europa": {+-- > "Germany": ["Berlin", "Bonn"],+-- > "Ukraine": ["Kiyv", "Gitomir", "Lviv"],+-- > "UnitedKingdom": ["London", "Glasgow"]+-- > }+-- >}++jMergesRec :: [Json] -> Json+jMergesRec [] = jEmpty+jMergesRec js = foldl1 jMergeRec js++--------------------------------------------------------------------------++-- | filter JSON objects +isObj :: JFilter+isObj (JObject o) = [JObject o]+isObj _ = []++-- | filter JSON arrays+-- Example +isArr :: JFilter+isArr (JArray a) = [JArray a]+isArr _ = []++-- | filter JSON strings+isStr :: JFilter+isStr (JString s) = [JString s]+isStr _ = []++-- | filter JSON numbers+isNum :: JFilter+isNum (JNumber n) = [JNumber n]+isNum _ = []++-- | filter JSON Bool+isBool :: JFilter+isBool (JBool p) = [JBool p]+isBool _ = []++-- | filter JSON null+isNull :: JFilter+isNull JNull = [JNull]+isNull _ = []++-- | filter primitive types+isPrimitive :: JFilter+isPrimitive (JString s) = [JString s]+isPrimitive (JNumber n) = [JNumber n]+isPrimitive (JBool p) = [JBool p]+isPrimitive JNull = [JNull]+isPrimitive _ = []++-- | get elements from object with key+getFromKey :: String -> JFilter+getFromKey k (JObject m) = Mb.catMaybes [(M.lookup k m)]+getFromKey _ _ = []++-- | get elements from object with keys+-- +-- Example:+-- +-- > pprint js = mapM_ putStrLn $ map (toString " ") js --pretty print +--+-- > query1 = getFromKeys ["Europa", "America", "Africa"] +-- > json1 = query1 merg +-- > ex1 = pprint json1+-- +-- Result:+--+-- > {+-- > "Germany": ["Berlin", "Bonn"],+-- > "Ukraine": ["Kiyv", "Gitomir", "Lviv"],+-- > "UnitedKingdom": ["London", "Glasgow"]+-- > }+-- > {+-- > "Canada": ["Toronto"],+-- > "USA": []+-- > }+-- > {+-- > +-- > }++getFromKeys :: [String] -> JFilter+getFromKeys ks (JObject m) = Mb.catMaybes $ map (\k -> (M.lookup k m)) (L.nub ks) +getFromKeys _ _ = []++-- | get all elements from object+getFromObj :: JFilter+getFromObj (JObject o) = M.elems o+getFromObj _ = []++-- | get all elements from array+getFromArr :: JFilter+getFromArr (JArray a) = a+getFromArr _ = []++-- | get element from array with index+getFromIndex :: Int -> JFilter+getFromIndex i (JArray a) = if i < length a then [a !! i] else []+getFromIndex _ _ = []++-- | get elements from array with indexes+getFromIndexes :: [Int] -> JFilter+getFromIndexes is ja = concat [getFromIndex i ja | i <- is]++-- | get all elements from object and array+getChildern :: JFilter+getChildern (JObject o) = M.elems o+getChildern (JArray a) = a+getChildern _ = []++-- | filter combinators+-- +-- Example:+-- +-- > query2 = query1 >>> getFromObj +-- > json2 = query2 merg+-- > ex2 = pprint json2+-- +-- Result:+-- +-- > ["Berlin", "Bonn"]+-- > ["Kiyv", "Gitomir", "Lviv"]+-- > ["London", "Glasgow"]+-- > ["Toronto"]+-- > []+-- +(>>>) :: JFilter -> JFilter -> JFilter +(f >>> g) t = concat [g t' | t' <- f t]++-- | filter combinators+(<+>) :: JFilter -> JFilter -> JFilter+(f <+> g) t = f t ++ g t++-- | filter combinators+orElse :: JFilter -> JFilter -> JFilter+orElse f g t+ | null res1 = g t+ | otherwise = res1+ where+ res1 = f t++-- | filter combinators+when :: JFilter -> JFilter -> JFilter+when f g t+ | null (g t) = [t]+ | otherwise = f t++-- | filter combinators+guards :: JFilter -> JFilter -> JFilter+guards g f t+ | null (g t) = []+ | otherwise = f t++-- | tree traversal filter for object+deepObj :: JFilter -> JFilter+deepObj f = f `orElse` (getFromObj >>> deepObj f)++-- | tree traversal filter for array+deepArr :: JFilter -> JFilter+deepArr f = f `orElse` (getFromArr >>> deepArr f)++-- | tree traversal filter for objects and arrays+--+-- Example:+--+-- > -- Qwery: All city Europa, America, Australia and Africa+-- > -- q31, q32, q33 is equal+-- > +-- > q31 = getFromKeys ["Europa", "America", "Africa", "Australia"] +-- > >>> (getFromArr `orElse` getFromObj)+-- > >>> (isStr `orElse` getFromArr)+-- > +-- > q32 = getFromKeys ["Europa", "America", "Africa", "Australia"] +-- > >>> (getFromObj `when` isObj)+-- > >>> getFromArr+-- > +-- > q33 = getFromKeys ["Europa", "America", "Africa", "Australia"] +-- > >>> +-- > deep getFromArr+-- >+-- +-- See also: <www.haskell.org/haskellwiki/HXT> +-- |+deep :: JFilter -> JFilter+deep f = f `orElse` (getChildern >>> deep f)++--- Debug ----------------------------------------------------------------++-- | pretty print query from JSON string+--+-- > debug (deep isPrimitive) "[1, [false, true, [null]]]" == "[1, false, true, null]"+--+debug :: JFilter -> String -> String+debug query jstr = case (fromString jstr) of+ Left errmsg -> error errmsg+ Right json -> PP.toString "- "$ JArray $ query json+