GitHub - pbrisbin/jsonpatch: Haskell package for parsing and applying JSON Patches (original) (raw)
jsonpatch
Haskell package for parsing and applying JSON Patches.
Example
Typical use cases need only one import:
Our example will make use of a few more libraries:
import Control.Exception (displayException) import Data.Aeson (FromJSON, ToJSON, Result(..), Value, fromJSON) import Data.Aeson.Encode.Pretty import Data.Aeson.QQ (aesonQQ) import Data.ByteString (ByteString) import Data.ByteString.Lazy qualified as BSL import Data.Text (Text) import GHC.Generics (Generic)
The FromJSON
instance can be used to build a [Patch]
:
patch :: [Patch] patch = fromResult $ fromJSON [aesonQQ| [ { "op": "replace", "path": "/baz", "value": "boo" }, { "op": "add", "path": "/hello", "value": ["world"] }, { "op": "remove", "path": "/foo" } ] |]
-- | Unsafe unwrapping for the sake of example fromResult :: Result a -> a fromResult (Success a) = a
The patches can then be applied to a document:
result :: Either PatchError Value result = patchValue patch [aesonQQ| { "baz": "qux", "foo": "bar" } |]
The result is in Either PatchError
, with displayException
available to get a user-friendly message.
main :: IO () main = either (fail . displayException) (BSL.putStr . encodePretty) result
The above program outputs:
{ "baz": "boo", "hello": ["world"] }
AsValue
Example
The polymorphic patchAsValue
function is also available, which provides the following benefits over patchValue
:
- The patches argument can be any
AsValue
(fromaeson-optics
), meaning you can give it directly aByteString
,Value
, orText
. Parse errors turning it into[Patch]
will be normalized toPatchError
. - The target argument can be any type with
FromJSON
andToJSON
. This means you can patch any of your domain types directly.AsValue
would've worked here too, but your domain types are far less likely to have that instance.
data Dog = Dog { name :: Text , isGood :: Bool } deriving stock Generic deriving anyclass (FromJSON, ToJSON)
fido :: Dog fido = Dog "fido" False -- gasp!
bytes :: ByteString bytes = "[{ "op":"replace", "path":"/isGood", "value":true }]"
result2 :: Either PatchError Dog result2 = patchAsValue bytes fido
main :: IO () main = either (fail . displayException) (BSL.putStr . encodePretty) result2
The above program outputs:
{ "isGood": true, "name": "fido" }
Quality
The full test suite from json-patch/json-patch-testspasses. However, some error cases have poor (or misleading) error messages at this time.
License
This package is licensed AGPLv3. See COPYING.