packages feed

hjpath 1.0 → 2.0

raw patch · 2 files changed

+56/−15 lines, 2 filesdep +hjsondep −RJsonPVP ok

version bump matches the API change (PVP)

Dependencies added: hjson

Dependencies removed: RJson

API changes (from Hackage documentation)

+ Text.JSON.JPath: jPathModify :: String -> (Json -> Json) -> String -> Either String String
+ Text.JSON.JPath: jPathModify' :: String -> (Json -> Json) -> Json -> Json
- Text.JSON.JPath: jPath :: String -> String -> Either String [JsonData]
+ Text.JSON.JPath: jPath :: String -> String -> Either String [Json]
- Text.JSON.JPath: jPath' :: String -> JsonData -> [JsonData]
+ Text.JSON.JPath: jPath' :: String -> Json -> [Json]

Files

Text/JSON/JPath.hs view
@@ -1,28 +1,48 @@-module Text.JSON.JPath (jPath, jPath') where+{- | I wanted to insert a description here, but got tired fighting with haddock escaping. Documentation: <http://bitcheese.net/wiki/code/hjpath>+-} +module Text.JSON.JPath (jPath, jPath', jPathModify, jPathModify') where+ import qualified Data.Map as Map+import Data.List import Data.Maybe-import Text.RJson+import Text.HJson as JSON import Text.ParserCombinators.Parsec.Combinator import Text.ParserCombinators.Parsec.Char import Text.ParserCombinators.Parsec.Prim -data Element = ObjectLookup String | ArrayLookup Int | WildcardLookup | DeepLookup deriving (Show)+data Element = ObjectLookup String | ArrayLookup Integer | WildcardLookup | DeepLookup deriving (Show)  -- |Evaluates JPath query on JSON String jPath :: String -- ^ JPath query 	-> String 	-- ^ JSON as String-	-> Either String [JsonData] -- ^ Either error text or list of results-jPath query s = let json = parseJsonString s+	-> Either String [Json] -- ^ (Left parsing error) or (Right results)+jPath query s = let json = JSON.fromString s 	in either (Left) (Right . jPath' query) json  -- |Evaluates JPath query on pre-parsed JSON jPath' :: String  -- ^ JPath query-	-> JsonData -- ^ Parsed JSON-	-> [JsonData] -- ^ List of results+	-> Json -- ^ Parsed JSON+	-> [Json] -- ^ List of results jPath' query v = let parsedQuery = parseExpression query 	in either (const []) (\q -> jPathP q v) parsedQuery +-- |Modifies JSON content under JPath expression+jPathModify :: String -- ^ JPath query+	-> (Json -> Json) -- ^ Element modifier function+	-> String -- ^ JSON as string+	-> Either String String -- ^ (Left parsing error) or (Right modified JSON as string)+jPathModify query modifier json = either (Left) (Right . JSON.toString . jPathModify' query modifier) $ JSON.fromString json++-- |jPathModify for pre-parsed JSON+jPathModify' :: String -- ^ JPath query+	-> (Json -> Json) -- ^ Element modifier function+	-> Json -- ^ JSON+	-> Json -- ^ modified JSON+jPathModify' query modifier json = either (const json) (\q -> (jPathModifyP q modifier json)) $ parseExpression query++-- private functions+ expression = do 	result <- element `sepBy` slash 	eof@@ -59,20 +79,41 @@  parseExpression = parse expression "JPath query" -jPathP :: [Element] -> JsonData -> [JsonData]+jPathP :: [Element] -> Json -> [Json] jPathP [] v = [v] jPathP (e:es) v = case e of 	ObjectLookup s -> case v of-		JDObject wtf -> maybe [] (jPathP es) $ s `Map.lookup` wtf+		JObject wtf -> maybe [] (jPathP es) $ s `Map.lookup` wtf 		otherwise -> [] 	ArrayLookup i -> case v of-		JDArray vs -> if i >= length vs || i < 0 - length vs then+		JArray vs -> if i >= genericLength vs || i < 0 - genericLength vs then 			[] 			else-			jPathP es $ vs !! (if i < 0 then length vs - abs i else i)+			jPathP es $ vs `genericIndex` (if i < 0 then genericLength vs - abs i else i) 		otherwise -> [] 	WildcardLookup -> case v of-		JDObject wtf -> concat $ map (jPathP es) (Map.elems wtf)-		JDArray vs -> concat $ map (jPathP es) vs+		JObject wtf -> concat $ map (jPathP es) (Map.elems wtf)+		JArray vs -> concat $ map (jPathP es) vs 		otherwise -> [] 	DeepLookup -> concat [jPathP (WildcardLookup:es) v, jPathP ([WildcardLookup, DeepLookup] ++ es) v]++jPathModifyP :: [Element] -> (Json -> Json) -> Json -> Json+jPathModifyP [] modifier v = modifier v+jPathModifyP (e:es) modifier v = let traverse = jPathModifyP es modifier in case e of+	ObjectLookup s -> case v of+		JObject wtf -> JObject $ Map.alter (Just . traverse . fromMaybe (JObject Map.empty)) s wtf+		otherwise -> v+	ArrayLookup i -> case v of+		JArray vs -> if i >= genericLength vs || i < 0 - genericLength vs then+			JArray vs+			else+			let num = if i < 0 then genericLength vs - abs i else i;+				(hd, tl) = genericSplitAt (num + 1) vs+				in JArray $ concat [init hd, [traverse (last hd)], tl]+				-- Ugly. why Data.List doesn't have 'modify by index' function+		otherwise -> v+	WildcardLookup -> case v of+		JObject wtf -> JObject $ Map.map (traverse) wtf+		JArray vs -> JArray $ map (traverse) vs+		otherwise -> v+	DeepLookup -> jPathModifyP (WildcardLookup:es) modifier  (jPathModifyP ([WildcardLookup, DeepLookup] ++ es) modifier v)
hjpath.cabal view
@@ -1,5 +1,5 @@ Name: hjpath-Version: 1.0+Version: 2.0 Synopsis: XPath-like syntax for querying JSON Category: Text Description: JPath is XPath-inspired query language to query JSON data.@@ -17,4 +17,4 @@  library  Exposed-Modules: Text.JSON.JPath- Build-Depends: base >= 4 && < 5, RJson, parsec >= 2.1, containers+ Build-Depends: base >= 4 && < 5, hjson, parsec >= 2.1, containers