Skip to content

Commit 0aadeb6

Browse files
authored
Merge pull request #3 from nikhilvavs/add_in_place
Bump gson version and remove duplicating in each operation
2 parents f83ffac + adbfd2a commit 0aadeb6

File tree

13 files changed

+227
-45
lines changed

13 files changed

+227
-45
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ repositories {
1212
}
1313

1414
dependencies {
15-
compile 'com.google.code.gson:gson:2.8.0'
15+
compile 'com.google.code.gson:gson:2.8.5'
1616
testCompile 'junit:junit:4.12'
1717
}
1818

src/main/java/com/tananaev/jsonpatch/JsonPatch.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@
2020
import com.google.gson.JsonElement;
2121
import com.tananaev.jsonpatch.gson.JsonPathSerializer;
2222
import com.tananaev.jsonpatch.operation.AbsOperation;
23+
import com.tananaev.jsonpatch.operation.InPlaceElementWrapper;
2324

2425
import java.util.LinkedList;
2526

2627
public class JsonPatch extends LinkedList<AbsOperation> {
2728

2829
public JsonElement apply(JsonElement original) {
29-
JsonElement result = original;
30+
JsonElement result = original.deepCopy();
31+
InPlaceElementWrapper inPlaceElement = new InPlaceElementWrapper(result);
3032
for ( AbsOperation operation: this){
31-
result = operation.apply(result);
33+
operation.applyInPlace(inPlaceElement);
3234
}
33-
return result;
35+
return inPlaceElement.getJsonElement();
3436
}
3537

3638
@Override

src/main/java/com/tananaev/jsonpatch/operation/AbsOperation.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.tananaev.jsonpatch.operation;
22

33
import com.google.gson.JsonElement;
4-
import com.google.gson.JsonParser;
54
import com.google.gson.annotations.SerializedName;
65
import com.tananaev.jsonpatch.JsonPath;
76

@@ -18,10 +17,24 @@ public AbsOperation(){
1817

1918
public abstract String getOperationName();
2019

21-
public abstract JsonElement apply( JsonElement original );
22-
23-
protected JsonElement duplicate(JsonElement original) {
24-
return new JsonParser().parse(original.toString());
25-
}
20+
/**
21+
* Applies the operation on the source and returns the patched object. The source is unmodified.
22+
* @param sourceElement to which the patch is to be applied
23+
* @return final json after patch is applied
24+
*/
25+
public JsonElement apply( JsonElement sourceElement ){
26+
JsonElement copiedSource = sourceElement.deepCopy();
27+
InPlaceElementWrapper inPlaceElement = new InPlaceElementWrapper(copiedSource);
28+
applyInPlace(inPlaceElement);
29+
return inPlaceElement.getJsonElement();
30+
};
31+
32+
/**
33+
* An optimised version of apply where the source is not copied and is directly modified if possible.
34+
* Updates the inPlaceElement to contain the patched json element.
35+
* Refer to {@link InPlaceElementWrapper} for details on why a wrapper is needed
36+
* @param inPlaceElement input to which the patch is to be applied
37+
*/
38+
public abstract void applyInPlace(InPlaceElementWrapper inPlaceElement );
2639

2740
}

src/main/java/com/tananaev/jsonpatch/operation/AddOperation.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@ public String getOperationName() {
2525
}
2626

2727
@Override
28-
public JsonElement apply(JsonElement original) {
29-
JsonElement result = duplicate( original );
30-
31-
JsonElement item = path.head().navigate(result);
28+
public void applyInPlace(InPlaceElementWrapper inPlaceElement){
29+
JsonElement sourceElement = inPlaceElement.getJsonElement();
30+
JsonElement item = path.head().navigate(sourceElement);
3231

3332
if ( item.isJsonObject() ){
3433
item.getAsJsonObject().add(path.tail(),data);
@@ -54,8 +53,6 @@ public JsonElement apply(JsonElement original) {
5453
}
5554

5655
}
57-
58-
return result;
5956
}
6057

6158
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.tananaev.jsonpatch.operation;
2+
3+
import com.google.gson.JsonElement;
4+
5+
/**
6+
* Wrapper class over json element to pass as an input for in place operations.
7+
* This is needed because we cannot convert actual JsonElement types into another in place
8+
* i.e, we cannot convert a JsonPrimitive (or other) into a JsonObject (or other) in-place
9+
* if needed by the patch operation.
10+
*/
11+
public class InPlaceElementWrapper {
12+
13+
private JsonElement jsonElement;
14+
15+
public JsonElement getJsonElement() {
16+
return jsonElement;
17+
}
18+
19+
public InPlaceElementWrapper(JsonElement element) {
20+
this.jsonElement = element;
21+
}
22+
23+
public void setJsonElement(JsonElement jsonElement) {
24+
this.jsonElement = jsonElement;
25+
}
26+
}

src/main/java/com/tananaev/jsonpatch/operation/MoveOperation.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,17 @@ public String getOperationName() {
2323
}
2424

2525
@Override
26-
public JsonElement apply(JsonElement original) {
27-
JsonElement result = duplicate( original );
26+
public void applyInPlace(InPlaceElementWrapper inPlaceElement) {
27+
JsonElement sourceElement = inPlaceElement.getJsonElement();
28+
JsonElement value = from.navigate(sourceElement);
2829

29-
JsonElement value = from.navigate(result);
30+
JsonElement existingElement = from.head().navigate(sourceElement);
31+
JsonElement destination = path.head().navigate(sourceElement);
3032

31-
JsonElement source = from.head().navigate(result);
32-
JsonElement destination = path.head().navigate(result);
33-
34-
if ( source.isJsonObject() ){
35-
source.getAsJsonObject().remove(from.tail());
36-
} else if ( source.isJsonArray() ){
37-
JsonArray array = source.getAsJsonArray();
33+
if ( existingElement.isJsonObject() ){
34+
existingElement.getAsJsonObject().remove(from.tail());
35+
} else if ( existingElement.isJsonArray() ){
36+
JsonArray array = existingElement.getAsJsonArray();
3837

3938
int index = (from.tail().equals("-")) ? array.size() : Integer.valueOf(from.tail());
4039

@@ -64,8 +63,6 @@ public JsonElement apply(JsonElement original) {
6463
array.add(stuff);
6564
}
6665
}
67-
68-
return result;
6966
}
7067

7168
}

src/main/java/com/tananaev/jsonpatch/operation/RemoveOperation.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ public String getOperationName() {
1616
}
1717

1818
@Override
19-
public JsonElement apply(JsonElement original) {
20-
JsonElement result = duplicate( original );
19+
public void applyInPlace(InPlaceElementWrapper inPlaceElement) {
2120

22-
JsonElement item = path.head().navigate(result);
21+
JsonElement item = path.head().navigate(inPlaceElement.getJsonElement());
2322

2423
if ( item.isJsonObject() ){
2524
item.getAsJsonObject().remove(path.tail());
@@ -31,7 +30,6 @@ public JsonElement apply(JsonElement original) {
3130
array.remove(index);
3231
}
3332

34-
return result;
3533
}
3634

3735
}

src/main/java/com/tananaev/jsonpatch/operation/ReplaceOperation.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ public String getOperationName() {
2222
}
2323

2424
@Override
25-
public JsonElement apply(JsonElement original) {
26-
JsonElement result = duplicate( original );
25+
public void applyInPlace(InPlaceElementWrapper inPlaceElement) {
2726

28-
JsonElement item = path.head().navigate(result);
27+
JsonElement item = path.head().navigate(inPlaceElement.getJsonElement());
2928

3029
if ( item.isJsonObject() ){
3130
JsonObject object = item.getAsJsonObject();
@@ -45,10 +44,9 @@ public JsonElement apply(JsonElement original) {
4544
}
4645

4746
} else {
48-
return data;
47+
inPlaceElement.setJsonElement(data);
4948
}
5049

51-
return result;
5250
}
5351

5452
}

src/test/java/com/tananaev/jsonpatch/test/OperationTest.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,13 @@
2222
import com.google.gson.JsonPrimitive;
2323
import com.tananaev.jsonpatch.JsonPath;
2424
import com.tananaev.jsonpatch.operation.AddOperation;
25+
import com.tananaev.jsonpatch.operation.InPlaceElementWrapper;
2526
import com.tananaev.jsonpatch.operation.ReplaceOperation;
2627
import org.junit.Assert;
2728
import org.junit.Test;
2829

2930
public class OperationTest {
3031

31-
@Test
32-
public void basicAddWorks(){
33-
JsonElement element = new JsonObject();
34-
35-
JsonElement result = new AddOperation(new JsonPath("/a"), new JsonObject() ).apply(element);
36-
37-
Assert.assertEquals("{\"a\":{}}", result.toString());
38-
}
3932

4033
@Test
4134
public void replaceRootNullWithPrimitive(){
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.tananaev.jsonpatch.test.operation;
2+
3+
import com.google.gson.JsonElement;
4+
import com.google.gson.JsonObject;
5+
import com.tananaev.jsonpatch.JsonPath;
6+
import com.tananaev.jsonpatch.operation.AddOperation;
7+
import com.tananaev.jsonpatch.operation.InPlaceElementWrapper;
8+
import org.junit.Assert;
9+
import org.junit.Test;
10+
11+
public class AddOperationTest {
12+
13+
@Test
14+
public void basicAddWorks(){
15+
JsonElement element = new JsonObject();
16+
String originalData = element.toString();
17+
18+
JsonElement result = new AddOperation(new JsonPath("/a"), new JsonObject() ).apply(element);
19+
20+
Assert.assertEquals(originalData, element.toString());
21+
Assert.assertEquals("{\"a\":{}}", result.toString());
22+
}
23+
24+
@Test
25+
public void basicInPlaceAddWorks(){
26+
JsonElement element = new JsonObject();
27+
InPlaceElementWrapper inPlaceElement = new InPlaceElementWrapper(element);
28+
AddOperation addOperation = new AddOperation(new JsonPath("/a"), new JsonObject());
29+
30+
addOperation.applyInPlace(inPlaceElement);
31+
JsonElement result = inPlaceElement.getJsonElement();
32+
33+
Assert.assertEquals("{\"a\":{}}", result.toString());
34+
}
35+
}

0 commit comments

Comments
 (0)