Skip to content

add flag to not generate Move or Copy operations. #81

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ buildscript {
repositories {
mavenCentral()
maven {
url "http://repo.springsource.org/plugins-release";
url "https://repo.springsource.org/plugins-release";
}
}
dependencies {
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/com/github/fge/jsonpatch/diff/DiffOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.github.fge.jsonpatch.diff;

/**
* Created by AMA on 24/09/2020.
*/
public class DiffOptions {

public static final boolean DIFF_DOESNT_REQUIRE_SOURCE = false;

final boolean diffDoesntRequireSource;

public static final DiffOptions DEFAULT_OPTIONS = new DiffOptions(DIFF_DOESNT_REQUIRE_SOURCE);

private DiffOptions(boolean diffDoesntRequireSource) {
this.diffDoesntRequireSource = diffDoesntRequireSource;
}

public boolean isDiffDoesntRequireSource() {
return diffDoesntRequireSource;
}

public static class Builder {
private boolean diffDoesntRequireSource = DIFF_DOESNT_REQUIRE_SOURCE;

public Builder diffDoesntRequireSource() {
diffDoesntRequireSource = true;
return this;
}

public Builder diffRequireSource() {
diffDoesntRequireSource = false;
return this;
}

public DiffOptions build(){
return new DiffOptions(diffDoesntRequireSource);
}

}
}
14 changes: 13 additions & 1 deletion src/main/java/com/github/fge/jsonpatch/diff/DiffProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,18 @@ final class DiffProcessor

private final Map<JsonPointer, JsonNode> unchanged;

private final DiffOptions options;
public static final boolean DIFF_DOESNT_REQUIRE_SOURCE = false;

private final List<DiffOperation> diffs = new ArrayList<DiffOperation>();

DiffProcessor(final Map<JsonPointer, JsonNode> unchanged)
DiffProcessor(final Map<JsonPointer, JsonNode> unchanged) {
this(unchanged, DiffOptions.DEFAULT_OPTIONS);
}

DiffProcessor(final Map<JsonPointer, JsonNode> unchanged, final DiffOptions options)
{
this.options = options;
this.unchanged = Collections.unmodifiableMap(new HashMap<JsonPointer, JsonNode>(unchanged));
}

Expand All @@ -56,6 +64,10 @@ void valueRemoved(final JsonPointer pointer, final JsonNode value)

void valueAdded(final JsonPointer pointer, final JsonNode value)
{
if (options.isDiffDoesntRequireSource()) {
diffs.add(DiffOperation.add(pointer, value));
return;
}
final int removalIndex = findPreviouslyRemoved(value);
if (removalIndex != -1) {
final DiffOperation removed = diffs.get(removalIndex);
Expand Down
25 changes: 22 additions & 3 deletions src/main/java/com/github/fge/jsonpatch/diff/JsonDiff.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import java.io.IOException;
import java.util.*;

import static com.github.fge.jsonpatch.diff.DiffProcessor.DIFF_DOESNT_REQUIRE_SOURCE;

/**
* JSON "diff" implementation
*
Expand Down Expand Up @@ -81,14 +83,25 @@ private JsonDiff()
*
* @since 1.9
*/

// public static JsonPatch asJsonPatch(final JsonNode source,
// final JsonNode target, false)
// {
// return
// }
public static JsonPatch asJsonPatch(final JsonNode source,
final JsonNode target)
final JsonNode target)
{
return asJsonPatch(source, target, DiffOptions.DEFAULT_OPTIONS);
}
public static JsonPatch asJsonPatch(final JsonNode source,
final JsonNode target, final DiffOptions options)
{
BUNDLE.checkNotNull(source, "common.nullArgument");
BUNDLE.checkNotNull(target, "common.nullArgument");
final Map<JsonPointer, JsonNode> unchanged
= getUnchangedValues(source, target);
final DiffProcessor processor = new DiffProcessor(unchanged);
final DiffProcessor processor = new DiffProcessor(unchanged, options);

generateDiffs(processor, JsonPointer.empty(), source, target);
return processor.getPatch();
Expand All @@ -103,10 +116,16 @@ public static JsonPatch asJsonPatch(final JsonNode source,
* @return the patch as a {@link JsonNode}
*/
public static JsonNode asJson(final JsonNode source, final JsonNode target)
{
return asJson(source, target, DiffOptions.DEFAULT_OPTIONS);
}


public static JsonNode asJson(final JsonNode source, final JsonNode target, final DiffOptions options)
{
final String s;
try {
s = MAPPER.writeValueAsString(asJsonPatch(source, target));
s = MAPPER.writeValueAsString(asJsonPatch(source, target, options));
return MAPPER.readTree(s);
} catch (IOException e) {
throw new RuntimeException("cannot generate JSON diff", e);
Expand Down
31 changes: 24 additions & 7 deletions src/test/java/com/github/fge/jsonpatch/diff/JsonDiffTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
import java.util.Iterator;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static com.github.fge.jsonpatch.diff.DiffProcessor.DIFF_DOESNT_REQUIRE_SOURCE;
import static org.assertj.core.api.Assertions.*;

public final class JsonDiffTest
{
Expand All @@ -53,17 +54,20 @@ public Iterator<Object[]> getPatchesOnly()
final List<Object[]> list = Lists.newArrayList();

for (final JsonNode node: testData)
list.add(new Object[] { node.get("first"), node.get("second") });
list.add(new Object[] {
node.get("first"), node.get("second"),
node.has("options") ? getLiteralOptions(node.get("options")) : DiffOptions.DEFAULT_OPTIONS
});

return list.iterator();
}

@Test(dataProvider = "getPatchesOnly")
public void generatedPatchAppliesCleanly(final JsonNode first,
final JsonNode second)
final JsonNode second, final DiffOptions options)
throws JsonPatchException
{
final JsonPatch patch = JsonDiff.asJsonPatch(first, second);
final JsonPatch patch = JsonDiff.asJsonPatch(first, second, options);
final JsonNode actual = patch.apply(first);

assertThat(EQUIVALENCE.equivalent(second, actual)).overridingErrorMessage(
Expand All @@ -82,21 +86,34 @@ public Iterator<Object[]> getLiteralPatches()
continue;
list.add(new Object[] {
node.get("message").textValue(), node.get("first"),
node.get("second"), node.get("patch")
node.get("second"), node.get("patch"),
node.has("options") ? getLiteralOptions(node.get("options")) : DiffOptions.DEFAULT_OPTIONS
});
}

return list.iterator();
}

public DiffOptions getLiteralOptions(JsonNode jsonNode) {
DiffOptions.Builder builder = new DiffOptions.Builder();
if (jsonNode.has("diffDoesntRequireSource")) {
if (jsonNode.get("diffDoesntRequireSource").booleanValue()){
builder.diffDoesntRequireSource();
} else {
builder.diffRequireSource();
}
}
return builder.build();
}

@Test(
dataProvider = "getLiteralPatches",
dependsOnMethods = "generatedPatchAppliesCleanly"
)
public void generatedPatchesAreWhatIsExpected(final String message,
final JsonNode first, final JsonNode second, final JsonNode expected)
final JsonNode first, final JsonNode second, final JsonNode expected, final DiffOptions options)
{
final JsonNode actual = JsonDiff.asJson(first, second);
final JsonNode actual = JsonDiff.asJson(first, second, options);

assertThat(EQUIVALENCE.equivalent(expected, actual)).overridingErrorMessage(
"patch is not what was expected\nscenario: %s\n"
Expand Down
39 changes: 39 additions & 0 deletions src/test/resources/jsonpatch/diff/diff.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,44 @@
"patch": [
{ "op": "move", "path": "/c", "from": "/a" }
]
},{
"message": "when diffDoesntRequireSource similar element is added",
"first": {
"a": "c"
},
"second": {
"a": "c",
"d": "c"
},
"patch": [
{ "op": "add", "path": "/d", "value": "c" }
],
"options": {
"diffDoesntRequireSource": true
}
},
{
"message": "when diffDoesntRequireSource similar element is removed then added",
"first": { "a": "b" },
"second": { "c": "b" },
"patch": [
{ "op": "remove", "path": "/a" },
{ "op": "add", "path": "/c", "value": "b" }
],
"options": {
"diffDoesntRequireSource": true
}

},
{
"message": "with default options, similar element removed then added is moved instead",
"first": { "a": "b" },
"second": { "c": "b" },
"patch": [
{ "op": "move", "path": "/c", "from": "/a" }
],
"options": {
}

}
]