thsutton / aeson-diff Goto Github PK
View Code? Open in Web Editor NEWGenerate and apply diffs between JSON documents.
License: BSD 2-Clause "Simplified" License
Generate and apply diffs between JSON documents.
License: BSD 2-Clause "Simplified" License
Consider, very carefully, using and supporting lens
.
In particular, get
and applyOperation
are optical.
The current implementation is pretty messy.
It would be great to be able to see what's in a patch as a human!
No reason to hide it?
Not sure what happened, but aeson-diff didn't build for Stackage Nightly:
Building executable 'json-patch' for aeson-diff-1.1.0.3..
[1 of 1] Compiling Main ( src/patch.hs, dist/build/json-patch/json-patch-tmp/Main.o )
src/patch.hs:31:24: error:
Ambiguous occurrence ‘Options’
It could refer to either ‘Data.Aeson.Options’,
imported from ‘Data.Aeson’ at src/patch.hs:7:1-27
(and originally defined in ‘aeson-1.2.2.0:Data.Aeson.Types.Internal’)
or ‘Main.Options’, defined at src/patch.hs:19:1
|
31 | optionParser :: Parser Options
| ^^^^^^^
src/patch.hs:62:8: error:
Ambiguous occurrence ‘Options’
It could refer to either ‘Data.Aeson.Options’,
imported from ‘Data.Aeson’ at src/patch.hs:7:1-27
(and originally defined in ‘aeson-1.2.2.0:Data.Aeson.Types.Internal’)
or ‘Main.Options’, defined at src/patch.hs:19:1
|
add an option to ignore key whose value is null, e.g.
{a : null } equal to {}
Please make a hackage release
diff(1)
and patch(1)
check that lines being deleted match what is expected before performing the operation. Add an option to generate a test
operations immediately preceding any remove
operation.
diff
json-diff
commandFAILURE: case3: Test Fails - Unexpected error `Error in $: Could not parse patch: expected Array, but encountered Object' was not 'Could not parse patch: when expecting a Array, encountered Object instead
Error in $: Could not parse patch: expected Array, encountered Object'.
SUCCESS: case2
SUCCESS: case1
Test suite examples: FAIL
Test suite logged to: dist/test/aeson-diff-1.1.0.5-examples.log
Test suite properties: RUNNING...
Test suite properties: PASS
Test suite logged to: dist/test/aeson-diff-1.1.0.5-properties.log
2 of 3 test suites (2 of 3 test cases) passed.
Is it possible to add this package to https://www.stackage.org/?
The master
branch already supports GHC-8.4.x but these changes weren't uploaded to hackage.
It would be nice to be able to use aeson-diff
in cabal based builds or in stack based builds without extra stack.yaml
chants :)
This library needs updating in light of the API changes in aeson 2.0.1.0.
See haskell/aeson#881 for a migration guide.
Add benchmarks
I was thinking of using this to build a proper PATCH update abstraction for servant, but standards are nice, right.
Do you think that Patch should encode like this? http://tools.ietf.org/html/rfc6902
Hi, thanks for writing this library! It's great for printing out much simplified test assertion data when asserting equality on objects with a JSON form (in leiu of a dedicated delta / diff framework).
I have noticed that when an element is moved in a list, I'm seeing an ADD/REMOVE instead of a MOVE. I assume this comes from the edit-distance library under the hood which presumably doesn't detect MOVE operations. If there is a cleanup stage it might be worth adding a rewrite rule to simplify forms of this shape.
Minimal repro
#! /usr/bin/env cabal
{- cabal:
build-depends: base, aeson, aeson-diff
-}
module Main where
import Data.Aeson
import Data.Aeson.Diff
main :: IO ()
main = do
let lst1 = toJSON ["a", "b", "c"]
lst2 = toJSON ["a", "c", "b"]
putStrLn . show $ diff lst1 lst2
got
Patch {patchOperations = [
Add {changePointer = Pointer {pointerPath = [AKey 1]}, changeValue = String "c"},
Rem {changePointer = Pointer {pointerPath = [AKey 3]}}]}
expected a Mov
.
I wanted to use the library with ghc 9.0.1 but it's not working because of the requirement for base < 4.16
I added allow-newer: true
to my stack.yaml file and it seems to work.
I believe just increasing the version number would be enough :)
thank you!
Example:
Prelude Data.Aeson.Diff Data.Aeson> let x = Ins ([OKey "foo"]) (String "bar")
Prelude Data.Aeson.Diff Data.Aeson> let y = Del ([OKey "foo"]) (String "bar")
Prelude Data.Aeson.Diff Data.Aeson> let z = Del ([OKey "foo"]) (String "baz")
Prelude Data.Aeson.Diff Data.Aeson> let a = patch (Patch [x, y]) (object [])
Prelude Data.Aeson.Diff Data.Aeson> let b = patch (Patch [x, z]) (object [])
Expected behaviour:
Prelude Data.Aeson.Diff Data.Aeson> a
Object (fromList [])
Prelude Data.Aeson.Diff Data.Aeson> b
Object (fromList [("foo",String "bar")]
Actual behaviour:
Prelude Data.Aeson.Diff Data.Aeson> a
Object (fromList [])
Prelude Data.Aeson.Diff Data.Aeson> b
Object (fromList [])
Somehow I was expecting the Del
operation to check whether the current value matches the changeValue
and do a conditional delete.
Am I wrong in assuming this? What is the purpose of changeValue
for Del
?
Removing keys whose values are arrays is broken. Example:
# original json
{ "foo": ["bar"], "baz": "quux"}
# patch
{ "op": "remove", "path": "/foo" }
# resulting json
{ "foo": ["bar"], "baz": "quux"}
This also breaks things that depend on remove
, such as replace
.
Consider the following:
import Data.Aeson as A
import Data.Aeson.Diff as AD
import Data.Map as M
foo :: Map Int String
foo = mempty
bar :: Map Int String
bar = M.fromList [(123, "asdf")]
encoded = A.encode (AD.diff (A.toJSON foo) (A.toJSON bar))
decoded :: Patch
Right decoded = A.eitherDecode encoded
applied = AD.patch decoded (A.toJSON foo)
In this example, we're computing a diff between two Map Int String
values. Note that these still produce string keys when encoded:
λ> putStrLn $ decodeUtf8 $ A.encode bar
{"123":"asdf"}
When we compute the diff and encode it, we get the following:
λ> putStrLn $ decodeUtf8 encoded
[{"op":"add","path":"/123","value":"asdf"}]
This "path" seems to be ambiguous, because when we try to decode it:
λ> decoded
Patch {patchOperations = [Add {changePointer = Pointer {pointerPath = [AKey 123]}, changeValue = String "asdf"}]}
The pointerPath
is read in as an AKey
rather than the expected OKey
. As a result, it fails to apply:
λ> applied
Error "Cannot follow pointer [123]. Expected array but got {}"
From briefly looking over RFC6902, it seems like the right thing to do is actually not to make a distinction between OKey
and AKey
? It seems like whether a given path component is an "object index" or "array index" should instead depend on which type of JSON object you find during patching. (I.e. if you encounter an array, then try to parse the value as a numeric index, otherwise treat it as a string key for an object.) What do you think?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.