ADD and REMOVE in a vector instead of MOVE
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.
btw I often use this utility to make the diffs easier to read during testing:
renderDiff :: Operation -> Text
renderDiff (Add (formatPointer -> p) (formatValue -> v)) = T.unwords ["ADD", p, v]
renderDiff (Cpy (formatPointer -> p1) (formatPointer -> p2)) = T.unwords ["COPY", p1, p2]
renderDiff (Mov (formatPointer -> p1) (formatPointer -> p2)) = T.unwords ["MOVE", p1, p2]
renderDiff (Rem (formatPointer -> p)) = T.unwords ["REMOVE", p]
renderDiff (Rep (formatPointer -> p) (formatValue -> v)) = T.unwords ["REPLACE", p, v]
renderDiff (Tst (formatPointer -> p) (formatValue -> v)) = T.unwords ["TEST", p, v]
formatValue :: Json.Value -> Text
formatValue = decodeUtf8 . toStrict . encode
I think real support for move operations is probably going to require moving to a proper tree diff algorithm, but I'll add a cleanup phase to handled very simple moves (i.e. moving a value from one key to a sibling key).