Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADD and REMOVE in a vector instead of MOVE #52

Open
symbiont-sam-halliday opened this issue Oct 29, 2019 · 2 comments
Open

ADD and REMOVE in a vector instead of MOVE #52

symbiont-sam-halliday opened this issue Oct 29, 2019 · 2 comments
Assignees

Comments

@symbiont-sam-halliday
Copy link

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.

@symbiont-sam-halliday
Copy link
Author

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

@thsutton
Copy link
Owner

thsutton commented Nov 7, 2019

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants