JsonPointerRemoval1981Test.java
package tools.jackson.databind.node;
import org.junit.jupiter.api.Test;
import tools.jackson.core.JsonPointer;
import tools.jackson.databind.*;
import tools.jackson.databind.testutil.DatabindTestUtil;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests for JsonPointer-based removal functionality ([databind#1981]).
*/
public class JsonPointerRemoval1981Test extends DatabindTestUtil
{
private final ObjectMapper MAPPER = newJsonMapper();
@Test
public void testRemoveSimpleProperty() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.put("a", 1);
root.put("b", 2);
root.put("c", 3);
// Remove property "b"
JsonNode removed = root.remove(JsonPointer.compile("/b"));
assertEquals(2, removed.asInt());
assertEquals(MAPPER.readTree(a2q("""
{
"a": 1,
"c": 3
}
""")), root);
}
@Test
public void testRemoveNestedProperty() throws Exception
{
String json = a2q("{'a':{'b':{'c':13,'d':14},'e':15},'f':16}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Remove nested property /a/b/c
JsonNode removed = root.remove(JsonPointer.compile("/a/b/c"));
assertEquals(13, removed.asInt());
assertEquals(MAPPER.readTree(
a2q("{'a':{'b':{'d':14},'e':15},'f':16}")),
root);
}
@Test
public void testRemoveArrayElement() throws Exception
{
ArrayNode array = MAPPER.createArrayNode();
array.add(10);
array.add(20);
array.add(30);
array.add(40);
// Remove element at index 1
JsonNode removed = array.remove(JsonPointer.compile("/1"));
assertEquals(20, removed.asInt());
assertEquals(MAPPER.readTree("[10,30,40]"), array);
}
@Test
public void testRemoveFromNestedArray() throws Exception
{
String json = a2q("{'array':[1,2,3,4,5]}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Remove array element at /array/2
JsonNode removed = root.remove(JsonPointer.compile("/array/2"));
assertEquals(3, removed.asInt());
assertEquals(MAPPER.readTree(a2q("{'array':[1,2,4,5]}")), root);
}
@Test
public void testRemoveMixedNestedStructure() throws Exception
{
String json = a2q("{'Image':{'Width':800,'Height':600,'IDs':[116,943,234,38793]}}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Remove array element /Image/IDs/2
JsonNode removed = root.remove(JsonPointer.compile("/Image/IDs/2"));
assertEquals(234, removed.asInt());
assertEquals(MAPPER.readTree(a2q(
"{'Image':{'Width':800,'Height':600,'IDs':[116,943,38793]}}")), root);
}
@Test
public void testRemoveWithCompiledPointer() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.put("x", 100);
root.put("y", 200);
// Use JsonPointer.compile() for path-based removal
JsonNode removed = root.remove(JsonPointer.compile("/x"));
assertEquals(100, removed.asInt());
assertEquals(MAPPER.readTree(a2q("{'y':200}")), root);
}
@Test
public void testRemoveNonExistentProperty() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.put("a", 1);
// Try to remove non-existent property
JsonNode removed = root.remove(JsonPointer.compile("/nonexistent"));
assertTrue(removed.isMissingNode());
// and non-existing array element too
removed = root.remove(JsonPointer.compile("/0"));
assertTrue(removed.isMissingNode());
// Structure should be unchanged
assertEquals(MAPPER.readTree(a2q("{'a':1}")), root);
}
@Test
public void testRemoveNonExistentArrayIndex() throws Exception
{
ArrayNode array = MAPPER.createArrayNode();
array.add(1);
array.add(2);
// Try to remove out-of-bounds index
JsonNode removed = array.remove(JsonPointer.compile("/10"));
assertTrue(removed.isMissingNode());
// and property (that arrays can't have)
removed = array.remove(JsonPointer.compile("/a"));
assertTrue(removed.isMissingNode());
// Array should be unchanged
assertEquals(MAPPER.readTree("[1, 2]"), array);
}
@Test
public void testRemoveNonExistentNestedPath() throws Exception
{
String json = a2q("{'a':{'b':1}}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Try to remove from non-existent nested path
JsonNode removed = root.remove(JsonPointer.compile("/a/x/y"));
assertTrue(removed.isMissingNode());
// Structure should be unchanged
assertEquals(MAPPER.readTree(json), root);
}
@Test
public void testRemoveEmptyPointer() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.put("a", 1);
// Empty pointer should return null (can't remove root from itself)
JsonNode removed = root.remove(JsonPointer.compile(""));
assertTrue(removed.isMissingNode());
// Structure should be unchanged
assertEquals(MAPPER.readTree(a2q("{'a':1}")), root);
}
@Test
public void testRemoveFromValueNode() throws Exception
{
String json = a2q("{'a':{'b':123}}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Try to remove from a value node (not a container)
JsonNode removed = root.remove(JsonPointer.compile("/a/b/c"));
assertTrue(removed.isMissingNode());
// Structure should be unchanged
assertEquals(MAPPER.readTree(json), root);
}
@Test
public void testRemovePropertyWithSpecialCharacters() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.put("a/b", 1);
root.put("c~d", 2);
root.put("normal", 3);
// Remove property with slash (escaped as ~1)
JsonNode removed = root.remove(JsonPointer.compile("/a~1b"));
assertEquals(1, removed.asInt());
assertFalse(root.has("a/b"));
// Remove property with tilde (escaped as ~0)
removed = root.remove(JsonPointer.compile("/c~0d"));
assertEquals(2, removed.asInt());
assertFalse(root.has("c~d"));
assertEquals(1, root.size());
assertTrue(root.has("normal"));
}
@Test
public void testRemoveEntireObject() throws Exception
{
String json = a2q("{'outer':{'inner':{'deep':42}}}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Remove entire inner object
JsonNode removed = root.remove(JsonPointer.compile("/outer/inner"));
assertTrue(removed.isObject());
assertEquals(42, removed.path("deep").asInt());
// Verify structure - inner should be gone
assertEquals(MAPPER.readTree(a2q("{'outer':{}}")), root);
}
@Test
public void testRemoveEntireArray() throws Exception
{
String json = a2q("{'data':{'values':[1,2,3,4,5]}}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Remove entire array
JsonNode removed = root.remove(JsonPointer.compile("/data/values"));
assertTrue(removed.isArray());
assertEquals(5, removed.size());
// Verify structure - values array should be gone
assertEquals(MAPPER.readTree(a2q("{'data':{}}")), root);
}
@Test
public void testRemoveFromEmptyObject() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
assertTrue(root.remove(JsonPointer.compile("/anything")).isMissingNode());
}
@Test
public void testRemoveFromEmptyArray() throws Exception
{
ArrayNode array = MAPPER.createArrayNode();
assertTrue(array.remove(JsonPointer.compile("/0")).isMissingNode());
}
@Test
public void testRemoveFirstAndLastArrayElements() throws Exception
{
ArrayNode array = MAPPER.createArrayNode();
array.add("first");
array.add("middle");
array.add("last");
// Remove first element
JsonNode removed = array.remove(JsonPointer.compile("/0"));
assertEquals("first", removed.asString());
assertEquals(2, array.size());
assertEquals("middle", array.get(0).asString());
// Remove last element (now at index 1)
removed = array.remove(JsonPointer.compile("/1"));
assertEquals("last", removed.asString());
assertEquals(1, array.size());
assertEquals("middle", array.get(0).asString());
}
@Test
public void testRemoveChainedOperations() throws Exception
{
String json = a2q("{'a':1,'b':2,'c':3,'d':4}");
ObjectNode root = (ObjectNode) MAPPER.readTree(json);
// Remove multiple properties in sequence using JsonPointer
assertNotNull(root.remove(JsonPointer.compile("/a")));
assertNotNull(root.remove(JsonPointer.compile("/c")));
assertNotNull(root.remove(JsonPointer.compile("/d")));
// Only 'b' should remain
assertEquals(1, root.size());
assertTrue(root.has("b"));
assertEquals(2, root.get("b").asInt());
}
@Test
public void testRemoveNullValueProperty() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.putNull("nullProp");
root.put("normalProp", 42);
// Remove the null property
JsonNode removed = root.remove(JsonPointer.compile("/nullProp"));
assertNotNull(removed);
assertTrue(removed.isNull());
assertEquals(1, root.size());
assertFalse(root.has("nullProp"));
assertTrue(root.has("normalProp"));
}
@Test
public void testRemoveWithEmptyStringPropertyName() throws Exception
{
ObjectNode root = MAPPER.createObjectNode();
root.put("", "empty key");
root.put("normal", "normal key");
// Remove property with empty string key (pointer is "/")
JsonNode removed = root.remove(JsonPointer.compile("/"));
assertNotNull(removed);
assertEquals("empty key", removed.asString());
assertEquals(1, root.size());
assertFalse(root.has(""));
assertTrue(root.has("normal"));
}
}