lattyware / elm-json-diff / Json.Diff

Create a JSON patch by inspecting the difference between two JSON values.

This has been implemented rather simply, and is probably not very optimised, but it should work for a lot of use cases.

diff : Json.Decode.Value -> Json.Decode.Value -> Json.Patch.Patch

Create a Patch that when applied to the first value will produce the second value.

This uses a relatively expensive, but not perfect weight function to decide what patch is best (it basically encodes the JSON to a string and looks at the length), but it should give pretty reasonable results most of the time. If you want something more efficient or accurate you can use diffWithCustomWeight.

This won't produce moves in the patch. If you use invertibleDiff and Invertible.merge you can merge adds and removes of the same value into moves.

Note that this diff doesn't search for duplicated values and so will never produces copies, and as such the patches will not be concise if that is a common operation in your case.

invertibleDiff : Json.Decode.Value -> Json.Decode.Value -> Json.Patch.Invertible.Patch

Create a patch just as with diff, but in the form of an Invertible.Patch which contains all the extra information required to invert the patch to return a document to its original form.

diffWithCustomWeight : (Json.Patch.Invertible.Patch -> Basics.Int) -> Json.Decode.Value -> Json.Decode.Value -> Json.Patch.Invertible.Patch

Do a diff with a custom weight. This returns an invertible patch, if you want a normal one use Invertible.toMinimalPatch on the result.

The default weight function is patch |> Invertible.toMinimalPatch |> Json.Patch.encoder |> Json.Encode.encode 0 |> String.length which is reasonably expensive.

The cheapest reasonable function you might want to use is List.length, which is generally OK, but will produce poor results if replacements involve large chunks of JSON.

If you always use invertible patches, then using Invertible.toPatch in the weight function over Invertible.toMinimalPatch would provide a more accurate weight.

cheapDiff : Json.Decode.Value -> Json.Decode.Value -> Json.Patch.Invertible.Patch

Does a diff without using any testing of multiple options. This makes computing the diff much cheaper, but is much more likely to produce less concise (but still correct) patches.

In particular, removing elements from the start of lists will produce changes for future elements, and lots of small changes may be created rather than doing a single replace more efficiently.