MyNixOS website logo
Description

JSON Patch parsing and application.

This is a Haskell library for parsing and applying JSON Patches

From https://www.json.org/:

JSON Patch is a format for describing changes to a JSON document. It can be used to avoid sending a whole document when only a part has changed. When used in combination with the HTTP PATCH method, it allows partial updates for HTTP APIs in a standards compliant way.

The patch documents are themselves JSON documents.

JSON Patch is specified in RFC 6902 from the IETF.

jsonpatch

Hackage Stackage Nightly Stackage LTS CI

Haskell package for parsing and applying JSON Patches.

Example

Typical use cases need only one import:

import Data.JSON.Patch

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:

  1. The patches argument can be any AsValue (from aeson-optics), meaning you can give it directly a ByteString, Value, or Text. Parse errors turning it into [Patch] will be normalized to PatchError.
  2. The target argument can be any type with FromJSON and ToJSON. 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-tests passes. However, some error cases have poor (or misleading) error messages at this time.

License

This package is licensed AGPLv3. See COPYING.

Metadata

Version

0.3.0.1

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-windows
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows