diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java index fdd47823ae..2e69a0abca 100644 --- a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java +++ b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java @@ -370,7 +370,7 @@ public ArrayNode removeAll() /* /********************************************************** - /* Extended ObjectNode API, mutators, generic; addXxx()/insertXxx() + /* Extended ObjectNode API, mutators, generic; addXxx()/insertXxx()/setXxx() /********************************************************** */ @@ -553,7 +553,7 @@ public ArrayNode add(BigInteger v) { } return _add(numberNode(v)); } - + /** * Method for adding specified String value at the end of this array. * @@ -776,7 +776,7 @@ public ArrayNode insert(int index, BigInteger v) { } return _insert(index, numberNode(v)); } - + /** * Method that will insert specified String * at specified position in this array. @@ -827,6 +827,181 @@ public ArrayNode insert(int index, byte[] v) { return _insert(index, binaryNode(v)); } + /** + * @return This array node, to allow chaining + */ + public ArrayNode setPOJO(int index, Object pojo) { + return _set(index, (pojo == null) ? nullNode() + : pojoNode(pojo)); + } + + /** + * @return This array node, to allow chaining + */ + public ArrayNode setRawValue(int index, RawValue raw) { + return _set(index, (raw == null) ? nullNode() + : rawValueNode(raw)); + } + + /** + * @return This node (to allow chaining) + */ + public ArrayNode setNull(int index) + { + return _set(index, nullNode()); + } + + /** + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, short v) { + return _set(index, numberNode(v)); + } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, Short v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v.shortValue())); + } + + /** + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, int v) { + return _set(index, numberNode(v)); + } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, Integer v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v.intValue())); + } + + /** + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, long v) { + return _set(index, numberNode(v)); + } + + /** + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, Long v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v.longValue())); + } + + /** + * Method for setting value of a field to specified numeric value. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, float v) { + return _set(index, numberNode(v)); + } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, Float v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v.floatValue())); + } + + /** + * Method for setting value of a field to specified numeric value. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, double v) { + return _set(index, numberNode(v)); + } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, Double v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v.doubleValue())); + } + + /** + * Method for setting value of a field to specified numeric value. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, BigDecimal v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v)); + } + + /** + * Method for setting value of a field to specified numeric value. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, BigInteger v) { + return _set(index, (v == null) ? nullNode() + : numberNode(v)); + } + + /** + * Method for setting value of a field to specified String value. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, String v) { + return _set(index, (v == null) ? nullNode() + : textNode(v)); + } + + /** + * Method for setting value of a field to specified String value. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, boolean v) { + return _set(index, booleanNode(v)); + } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, Boolean v) { + return _set(index, (v == null) ? nullNode() + : booleanNode(v.booleanValue())); + } + + /** + * Method for setting value of a field to specified binary value + * + * @return This node (to allow chaining) + */ + public ArrayNode set(int index, byte[] v) { + return _set(index, (v == null) ? nullNode() + : binaryNode(v)); + } + /* /********************************************************** /* Standard methods @@ -862,6 +1037,14 @@ public int hashCode() { /********************************************************** */ + protected ArrayNode _set(int index, JsonNode node) { + if (index < 0 || index >= _children.size()) { + throw new IndexOutOfBoundsException("Illegal index "+ index +", array size "+size()); + } + _children.set(index, node); + return this; + } + protected ArrayNode _add(JsonNode node) { _children.add(node); return this; diff --git a/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java index 43beaf2897..b077904ec5 100644 --- a/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java @@ -8,8 +8,10 @@ import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import com.fasterxml.jackson.databind.util.RawValue; import static java.util.Arrays.asList; +import static org.junit.Assert.*; /** * Additional tests for {@link ArrayNode} container class. @@ -61,7 +63,7 @@ public void testDirectCreation() throws IOException // change to text n.set(1, text); assertSame(text, n.get(1)); - n.set(0, null); + n.set(0, (JsonNode) null); assertTrue(n.get(0).isNull()); // and finally, clear it all @@ -130,6 +132,62 @@ public void testDirectCreation2() throws IOException assertTrue(n.get(0).isNull()); } + public void testArraySet() throws IOException { + final ArrayNode array = JsonNodeFactory.instance.arrayNode(); + for (int i = 0; i < 20; i++) { + array.add("Original Data"); + } + + array.setPOJO(0, "MyPojo"); + array.setRawValue(1, new RawValue("MyRawValue")); + array.setNull(2); + array.set(3, (short) 155); + array.set(4, Short.valueOf((short) 130)); + array.set(5, 132); + array.set(6, Integer.valueOf(452)); + array.set(7, 4342L); + array.set(8, Long.valueOf(154242L)); + array.set(9, 1.22f); + array.set(10, Float.valueOf(242.1f)); + array.set(11, 132.212D); + array.set(12, Double.valueOf(231.3D)); + array.set(13, BigDecimal.TEN); + array.set(14, BigInteger.ONE); + array.set(15, "Modified Data"); + array.set(16, true); + array.set(17, Boolean.FALSE); + array.set(18, new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + + assertEquals("MyPojo", ((POJONode) array.get(0)).getPojo()); + assertEquals(new RawValue("MyRawValue"), ((POJONode) array.get(1)).getPojo()); + assertEquals(NullNode.instance, array.get(2)); + assertEquals((short) 155, array.get(3).shortValue()); + assertEquals((short) 130, array.get(4).shortValue()); + assertEquals(132, array.get(5).intValue()); + assertEquals(452, array.get(6).intValue()); + assertEquals(4342L, array.get(7).longValue()); + assertEquals(154242L, array.get(8).longValue()); + assertEquals(1.22f, array.get(9).floatValue()); + assertEquals(242.1f, array.get(10).floatValue()); + assertEquals(132.212D, array.get(11).doubleValue()); + assertEquals(231.3D, array.get(12).doubleValue()); + assertEquals(0, BigDecimal.TEN.compareTo(array.get(13).decimalValue())); + assertEquals(BigInteger.ONE, array.get(14).bigIntegerValue()); + assertEquals("Modified Data", array.get(15).textValue()); + assertTrue(array.get(16).booleanValue()); + assertFalse(array.get(17).booleanValue()); + assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, array.get(18).binaryValue()); + + assertEquals(20, array.size()); + for (int i = 0; i < 20; i++) { + if (i <= 18) { + assertNotEquals("Original Data", array.get(i).textValue()); + } else { + assertEquals("Original Data", array.get(i).textValue()); + } + } + } + public void testArrayViaMapper() throws Exception { final String JSON = "[[[-0.027512,51.503221],[-0.008497,51.503221],[-0.008497,51.509744],[-0.027512,51.509744]]]"; @@ -233,7 +291,42 @@ public void testNullInserts() assertTrue(node.isNull()); } } - + + public void testNullSet() + { + JsonNodeFactory f = objectMapper().getNodeFactory(); + ArrayNode array = f.arrayNode(3); + + for (int i = 0; i < 14; i++) { + array.add("Not Null"); + } + + for (JsonNode node : array) { + assertFalse(node.isNull()); + } + + array.set(0, (BigDecimal) null); + array.set(1, (BigInteger) null); + array.set(2, (Boolean) null); + array.set(3, (byte[]) null); + array.set(4, (Double) null); + array.set(5, (Float) null); + array.set(6, (Integer) null); + array.set(7, (Short) null); + array.set(8, (JsonNode) null); + array.set(9, (Long) null); + array.set(10, (String) null); + array.setNull(11); + array.setRawValue(12, null); + array.setPOJO(13, null); + + assertEquals(14, array.size()); + + for (JsonNode node : array) { + assertTrue(node.isNull()); + } + } + public void testNullChecking() { ArrayNode a1 = JsonNodeFactory.instance.arrayNode();