Skip to content

Commit bcd64ac

Browse files
committed
Fix #4997: add null checks for ObjectNode keys
1 parent c2aee19 commit bcd64ac

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Project: jackson-databind
6060
(fix by Joo-Hyuk K)
6161
#4963: Serializing `Map.Entry` as Bean with `@JsonFormat.shape = Shape.OBJECT`
6262
fails on JDK 17+
63+
#4997: `ObjectNode` put methods should do null check for key
6364
6465
2.18.3 (28-Feb-2025)
6566

src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java

+14-11
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ public ObjectNode with(String exprOrProperty) {
8787
.getClass().getName() + "`)");
8888
}
8989
ObjectNode result = objectNode();
90-
_children.put(exprOrProperty, result);
91-
return result;
90+
return _put(exprOrProperty, result);
9291
}
9392

9493
@Override
@@ -132,7 +131,7 @@ public ArrayNode withArray(String exprOrProperty)
132131
.getClass().getName() + "`)");
133132
}
134133
ArrayNode result = arrayNode();
135-
_children.put(exprOrProperty, result);
134+
_put(exprOrProperty, result);
136135
return result;
137136
}
138137

@@ -625,6 +624,9 @@ public <T extends JsonNode> T set(String propertyName, JsonNode value)
625624
* Method for adding given properties to this object node, overriding
626625
* any existing values for those properties.
627626
*<p>
627+
* NOTE: {@code null} keys are not allowed; ({@code null} values get
628+
* converted to a {@link NullNode}).
629+
*<p>
628630
* NOTE: co-variant return type since 2.10
629631
*
630632
* @param properties Properties to add
@@ -641,7 +643,7 @@ public <T extends JsonNode> T setAll(Map<String,? extends JsonNode> properties)
641643
if (n == null) {
642644
n = nullNode();
643645
}
644-
_children.put(en.getKey(), n);
646+
_put(en.getKey(), n);
645647
}
646648
return (T) this;
647649
}
@@ -669,7 +671,7 @@ public <T extends JsonNode> T setAll(ObjectNode other)
669671
* Method for replacing value of specific property with passed
670672
* value, and returning value (or null if none).
671673
*
672-
* @param propertyName Property of which value to replace
674+
* @param propertyName Property of which value to replace: must not be {@code null}
673675
* @param value Value to set property to, replacing old value if any
674676
*
675677
* @return Old value of the property; null if there was no such property
@@ -682,7 +684,7 @@ public JsonNode replace(String propertyName, JsonNode value)
682684
if (value == null) { // let's not store 'raw' nulls but nodes
683685
value = nullNode();
684686
}
685-
return _children.put(propertyName, value);
687+
return _children.put(Objects.requireNonNull(propertyName), value);
686688
}
687689

688690
/**
@@ -730,7 +732,7 @@ public <T extends JsonNode> T without(Collection<String> propertyNames)
730732
/**
731733
* Method that will set specified property, replacing old value, if any.
732734
*
733-
* @param propertyName Name of property to set
735+
* @param propertyName Name of property to set (must not be {@code null})
734736
* @param value Value to set to property; if null, will be converted
735737
* to a {@link NullNode} first (to remove a property, call
736738
* {@link #remove} instead).
@@ -746,7 +748,7 @@ public JsonNode put(String propertyName, JsonNode value)
746748
if (value == null) { // let's not store 'raw' nulls but nodes
747749
value = nullNode();
748750
}
749-
return _children.put(propertyName, value);
751+
return _children.put(Objects.requireNonNull(propertyName), value);
750752
}
751753

752754
/**
@@ -763,7 +765,7 @@ public JsonNode put(String propertyName, JsonNode value)
763765
* }
764766
*</code>
765767
*
766-
* @param propertyName Name of property to set
768+
* @param propertyName Name of property to set (must not be {@code null})
767769
* @param value Value to set to property (if and only if it had no value previously);
768770
* if null, will be converted to a {@link NullNode} first.
769771
*
@@ -777,7 +779,7 @@ public JsonNode putIfAbsent(String propertyName, JsonNode value)
777779
if (value == null) { // let's not store 'raw' nulls but nodes
778780
value = nullNode();
779781
}
780-
return _children.putIfAbsent(propertyName, value);
782+
return _children.putIfAbsent(Objects.requireNonNull(propertyName), value);
781783
}
782784

783785
/**
@@ -1176,9 +1178,10 @@ public int hashCode()
11761178
/**********************************************************
11771179
*/
11781180

1181+
// @since 2.19
11791182
protected ObjectNode _put(String propertyName, JsonNode value)
11801183
{
1181-
_children.put(propertyName, value);
1184+
_children.put(Objects.requireNonNull(propertyName), value);
11821185
return this;
11831186
}
11841187
}

src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java

+17
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,23 @@ public void testNullChecking2()
279279
dest.setAll(src);
280280
}
281281

282+
// for [databind#346]
283+
@Test
284+
public void testNullKeyChecking()
285+
{
286+
ObjectNode src = MAPPER.createObjectNode();
287+
assertThrows(NullPointerException.class, () -> src.put(null, "a"));
288+
assertThrows(NullPointerException.class, () -> src.put(null, 123));
289+
assertThrows(NullPointerException.class, () -> src.put(null, 123L));
290+
assertThrows(NullPointerException.class, () -> src.putNull(null));
291+
292+
assertThrows(NullPointerException.class, () -> src.set(null, BooleanNode.TRUE));
293+
assertThrows(NullPointerException.class, () -> src.replace(null, BooleanNode.TRUE));
294+
295+
assertThrows(NullPointerException.class, () -> src.setAll(Collections.singletonMap(null,
296+
MAPPER.createArrayNode())));
297+
}
298+
282299
@Test
283300
public void testRemove()
284301
{

0 commit comments

Comments
 (0)