json-query 0.2.1.0 → 0.2.2.0
raw patch · 5 files changed
+69/−8 lines, 5 filesdep ~scientific-notationdep ~transformers
Dependency ranges changed: scientific-notation, transformers
Files
- CHANGELOG.md +8/−0
- json-query.cabal +3/−3
- src/Json/Errors.hs +20/−2
- src/Json/Parser.hs +17/−1
- src/Json/Path.hs +21/−2
CHANGELOG.md view
@@ -1,5 +1,13 @@ # Revision history for json-query +## 0.2.2.0 -- 2023-08-09++* Add `Json.Errors.hPut` to make it less verbose to print+ parse errors.+* Add `Json.Parser.foldSmallArray`+* Add variant of `Json.Path.query` that returns Null when path is+ not found.+ ## 0.2.1.0 -- 2021-07-15 * Allow building with GHC 9.2.3
json-query.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: json-query-version: 0.2.1.0+version: 0.2.2.0 synopsis: Kitchen sink for querying JSON description: The library complements json-syntax by making available several@@ -31,8 +31,8 @@ , bytestring >=0.10 && <0.12 , contiguous >=0.6.1 , json-syntax >=0.2.2 && <0.3- , primitive >=0.7 && <0.8- , primitive-unlifted >=0.1.3 && <0.2+ , primitive >=0.7 && <0.10+ , primitive-unlifted >=0.1.3 && <2.2 , profunctors >=5.6 , scientific-notation >=0.1.5 && <0.2 , text-short >=0.1.3 && <0.2
src/Json/Errors.hs view
@@ -10,18 +10,20 @@ -- * Encoding , encode , builderUtf8+ , hPut -- * Create , singleton -- * Conversion , toSmallArray ) where +import Control.Monad.ST (runST)+import Data.ByteString.Short.Internal (ShortByteString(SBS)) import Data.Bytes.Builder (Builder) import Data.Primitive (SmallArray) import Data.Text.Short (ShortText)-import Data.ByteString.Short.Internal (ShortByteString(SBS))-import Control.Monad.ST (runST) import Json.Error (Error)+import System.IO (Handle) import qualified Data.Bytes.Builder as Builder import qualified Data.Bytes.Chunks as ByteChunks@@ -48,6 +50,8 @@ singleton :: Error -> Errors singleton = ErrorsOne +-- | Convert errors to builder. The errors are separated by+-- a pair of characters: comma and space. builderUtf8 :: Errors -> Builder builderUtf8 errs = let len = countErrors errs@@ -57,6 +61,20 @@ Arr.foldMap (\e -> Builder.ascii2 ',' ' ' <> Error.builderUtf8 e) (Arr.slice errArr 1 (len - 1))++-- | Print errors to the provided handle. Typically, @System.IO.stderr@+-- is provided as the handle. Each encoded error is suffixed with a newline.+--+-- This is a convenience function for the common case where, after a+-- failed parse, an application prints out all parse errors and then exits.+hPut :: Handle -> Errors -> IO ()+hPut h errs = do+ let len = countErrors errs+ errArr = makeErrorArray len errs+ bldr = Arr.foldMap+ (\e -> Error.builderUtf8 e <> Builder.ascii '\n')+ errArr+ in ByteChunks.hPut h (Builder.run 128 bldr) -- | Convert errors to array. toSmallArray :: Errors -> SmallArray Error
src/Json/Parser.hs view
@@ -20,6 +20,7 @@ , members -- * Arrays , smallArray+ , foldSmallArray , traverseMembers -- * Specific Data Constructors , object@@ -179,7 +180,7 @@ Nothing -> Left (Errors.singleton (Error{context=p',message="key not found: " <> name})) Just Member{value} -> runParser (f value) p' --- | Variant of 'key' that supplies the JSON value @null to the+-- | Variant of 'key' that supplies the JSON value @null@ to the -- callback if the key is not found. Using this parser combinators implies -- that there is no distinction between @null@ and an absent value in -- the encoding scheme.@@ -215,6 +216,21 @@ pure (ix + 1) ) 0 xs lift (PM.unsafeFreezeSmallArray dst)++-- | Run the parser against every element in a 'SmallArray', updating an+-- accumulator at each step. Folds from left to right. This adjusts+-- the context at each element. Typically, type @a@ is @Value@.+foldSmallArray :: (b -> a -> Parser b) -> b -> SmallArray a -> Parser b+{-# inline foldSmallArray #-}+foldSmallArray f acc0 xs = Parser $ \ !p -> runST do+ -- TODO: make sure tuples get elided+ runExceptT $ do+ (!_,r) <- foldlM+ (\( !ix, !acc) x -> do+ !acc' <- ExceptT (pure (runParser (f acc x) (Index ix p)))+ pure (ix + 1, acc')+ ) (0,acc0) xs+ pure r -- | Traverse the members. The adjusts the context at each member. traverseMembers :: (Member -> Parser a) -> SmallArray Member -> Parser (SmallArray a)
src/Json/Path.hs view
@@ -9,13 +9,14 @@ , builderUtf8 -- * Lookup , query+ , query' -- * Reverse , reverse ) where import Prelude hiding (reverse) -import Json (Value(Object,Array),Member(Member))+import Json (Value(Object,Array,Null),Member(Member)) import Data.Primitive (ByteArray(ByteArray)) import Data.Text.Short (ShortText) import Data.Bytes.Builder (Builder)@@ -53,7 +54,8 @@ <> Builder.ascii ']' <> go p --- | Search for an element at the given path.+-- | Search for an element at the given path. Returns 'Nothing' if+-- anything in the path is missing. query :: Path -> Value -> Maybe Value query = go where go Nil v = Just v@@ -68,6 +70,23 @@ in go p e else Nothing go _ _ = Nothing++-- | Variant of 'query' that returns 'Null' if anything in the path+-- is missing.+query' :: Path -> Value -> Value+query' = go where+ go Nil v = v+ go (Key k p) (Object mbrs) = go p $ foldr+ (\(Member key val) other -> if key == k+ then val+ else other+ ) Null mbrs+ go (Index i p) (Array vs) = if i < PM.sizeofSmallArray vs+ then+ let !(# e #) = PM.indexSmallArray## vs i+ in go p e+ else Null+ go _ _ = Null ba2st :: ByteArray -> ShortText ba2st (ByteArray x) = TS.fromShortByteStringUnsafe (SBS x)