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

[json-node] Add copy() and unmodifible() for deep copy options #302

Merged
merged 1 commit into from
Dec 12, 2024
Merged
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
18 changes: 18 additions & 0 deletions json-node/src/main/java/io/avaje/json/node/JsonArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ public String toString() {
return text();
}

@Override
public JsonArray unmodifiable() {
final var newList = new ArrayList<JsonNode>(children.size());
for (JsonNode child : children) {
newList.add(child.unmodifiable());
}
return of(newList);
}

@Override
public JsonArray copy() {
final var newList = new ArrayList<JsonNode>(children.size());
for (JsonNode child : children) {
newList.add(child.copy());
}
return new JsonArray(newList);
}

@Override
public Type type() {
return Type.ARRAY;
Expand Down
12 changes: 11 additions & 1 deletion json-node/src/main/java/io/avaje/json/node/JsonBoolean.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.avaje.json.node;

public final class JsonBoolean implements JsonNode {
public final /*value*/ class JsonBoolean implements JsonNode {

private final boolean value;

Expand All @@ -17,6 +17,16 @@ public String toString() {
return text();
}

@Override
public JsonBoolean unmodifiable() {
return this;
}

@Override
public JsonBoolean copy() {
return this;
}

@Override
public Type type() {
return Type.BOOLEAN;
Expand Down
12 changes: 11 additions & 1 deletion json-node/src/main/java/io/avaje/json/node/JsonDecimal.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import java.math.BigDecimal;

public final class JsonDecimal implements JsonNumber {
public final /*value*/ class JsonDecimal implements JsonNumber {

private final BigDecimal value;

Expand All @@ -21,6 +21,16 @@ public String toString() {
return text();
}

@Override
public JsonDecimal unmodifiable() {
return this;
}

@Override
public JsonDecimal copy() {
return this;
}

@Override
public Type type() {
return Type.NUMBER;
Expand Down
12 changes: 11 additions & 1 deletion json-node/src/main/java/io/avaje/json/node/JsonDouble.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import java.math.BigDecimal;

public final class JsonDouble implements JsonNumber {
public final /*value*/ class JsonDouble implements JsonNumber {

private final double value;

Expand All @@ -21,6 +21,16 @@ public String toString() {
return text();
}

@Override
public JsonDouble unmodifiable() {
return this;
}

@Override
public JsonDouble copy() {
return this;
}

@Override
public Type type() {
return Type.NUMBER;
Expand Down
12 changes: 11 additions & 1 deletion json-node/src/main/java/io/avaje/json/node/JsonInteger.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import java.math.BigDecimal;

public final class JsonInteger implements JsonNumber {
public final /*value*/ class JsonInteger implements JsonNumber {

private final int value;

Expand All @@ -21,6 +21,16 @@ public String toString() {
return text();
}

@Override
public JsonInteger unmodifiable() {
return this;
}

@Override
public JsonInteger copy() {
return this;
}

@Override
public Type type() {
return Type.NUMBER;
Expand Down
12 changes: 11 additions & 1 deletion json-node/src/main/java/io/avaje/json/node/JsonLong.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import java.math.BigDecimal;

public final class JsonLong implements JsonNumber {
public final /*value*/ class JsonLong implements JsonNumber {

private final long value;

Expand All @@ -21,6 +21,16 @@ public String toString() {
return text();
}

@Override
public JsonLong unmodifiable() {
return this;
}

@Override
public JsonLong copy() {
return this;
}

@Override
public Type type() {
return Type.NUMBER;
Expand Down
10 changes: 10 additions & 0 deletions json-node/src/main/java/io/avaje/json/node/JsonNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ public boolean isObject() {
*/
String text();

/**
* Return an unmodifiable deep copy of the JsonNode.
*/
JsonNode unmodifiable();

/**
* Return a mutable deep copy of the JsonNode.
*/
JsonNode copy();

/**
* Find a node given a path using dot notation.
* @param path The path in dot notation
Expand Down
18 changes: 18 additions & 0 deletions json-node/src/main/java/io/avaje/json/node/JsonObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,24 @@ public String text() {
return children.toString();
}

@Override
public JsonObject unmodifiable() {
final var mapCopy = new LinkedHashMap<String,JsonNode>();
for (Map.Entry<String, JsonNode> entry : children.entrySet()) {
mapCopy.put(entry.getKey(), entry.getValue().unmodifiable());
}
return JsonObject.of(mapCopy);
}

@Override
public JsonObject copy() {
final var mapCopy = new LinkedHashMap<String,JsonNode>();
for (Map.Entry<String, JsonNode> entry : children.entrySet()) {
mapCopy.put(entry.getKey(), entry.getValue().copy());
}
return new JsonObject(mapCopy);
}

/**
* Return true if the json object contains no elements.
*/
Expand Down
12 changes: 11 additions & 1 deletion json-node/src/main/java/io/avaje/json/node/JsonString.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.avaje.json.node;

public final class JsonString implements JsonNode {
public final /*value*/ class JsonString implements JsonNode {

private final String value;

Expand All @@ -17,6 +17,16 @@ public String toString() {
return text();
}

@Override
public JsonString unmodifiable() {
return this;
}

@Override
public JsonString copy() {
return this;
}

@Override
public Type type() {
return Type.STRING;
Expand Down
28 changes: 28 additions & 0 deletions json-node/src/test/java/io/avaje/json/node/JsonArrayTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class JsonArrayTest {

Expand Down Expand Up @@ -87,4 +88,31 @@ void add() {
assertThat(elements.get(4)).isInstanceOf(JsonObject.class);
}

@Test
void copy() {
final JsonArray source = JsonArray.create()
.add("foo")
.add(JsonObject.create().add("b", 42));

JsonArray copy = source.copy();
assertThat(copy.toString()).isEqualTo(source.toString());

copy.add("canMutate");
assertThat(copy.size()).isEqualTo(3);
assertThat(source.size()).isEqualTo(2);
}

@Test
void unmodifiable() {
final JsonArray source = JsonArray.create()
.add("foo")
.add(JsonObject.create().add("b", 42));

JsonArray copy = source.unmodifiable();
assertThat(copy.toString()).isEqualTo(source.toString());

assertThatThrownBy(() -> copy.add("canMutate"))
.isInstanceOf(UnsupportedOperationException.class);
}

}
29 changes: 28 additions & 1 deletion json-node/src/test/java/io/avaje/json/node/JsonObjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class JsonObjectTest {

Expand Down Expand Up @@ -116,4 +116,31 @@ void findNested() {

assertThat(node.extract("address.other.deep")).isEqualTo("one");
}

@Test
void copy() {
final JsonObject source = JsonObject.create()
.add("name", "foo")
.add("other", JsonObject.create().add("b", 42));

JsonObject copy = source.copy();
assertThat(copy.toString()).isEqualTo(source.toString());

copy.add("canMutate", true);
assertThat(copy.containsKey("canMutate")).isTrue();
assertThat(source.containsKey("canMutate")).isFalse();
}

@Test
void unmodifiable() {
final JsonObject source = JsonObject.create()
.add("name", "foo")
.add("other", JsonObject.create().add("b", 42));

JsonObject copy = source.unmodifiable();
assertThat(copy.toString()).isEqualTo(source.toString());

assertThatThrownBy(() -> copy.add("canMutate", true))
.isInstanceOf(UnsupportedOperationException.class);
}
}
Loading