Skip to content

Commit 78dce0e

Browse files
committed
Merge branch '2.10'
2 parents 3e5e6db + 8f0b80d commit 78dce0e

File tree

11 files changed

+251
-10
lines changed

11 files changed

+251
-10
lines changed

release-notes/VERSION-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Project: jackson-databind
66

77
2.10.0.pr2 (not yet released)
88

9+
#2237: Add "required" methods in `JsonNode`: `required(String | int)`,
10+
`requiredAt(JsonPointer)`
911
#2331: `JsonMappingException` through nested getter with generic wildcard return type
1012
(reported by sunchezz89@github)
1113
#2336: `MapDeserializer` can not merge `Map`s with polymorphic values

src/main/java/com/fasterxml/jackson/databind/JsonNode.java

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ public final boolean isBinary() {
389389
* if node is a JSON String representing integral number, or boolean.
390390
*/
391391
public boolean canConvertToLong() { return false; }
392-
392+
393393
/*
394394
/**********************************************************************
395395
/* Public API, straight value access
@@ -477,7 +477,7 @@ public byte[] binaryValue() throws IOException {
477477
* nodes.
478478
*/
479479
public long longValue() { return 0L; }
480-
480+
481481
/**
482482
* Returns 32-bit floating value for this node, <b>if and only if</b>
483483
* this node is numeric ({@link #isNumber} returns true). For other
@@ -655,6 +655,68 @@ public boolean asBoolean(boolean defaultValue) {
655655
return defaultValue;
656656
}
657657

658+
/*
659+
/**********************************************************************
660+
/* Public API, extended traversal (2.10) with "required()"
661+
/**********************************************************************
662+
*/
663+
664+
/**
665+
* @since 2.10
666+
*/
667+
public <T extends JsonNode> T require() {
668+
return _this();
669+
}
670+
671+
/**
672+
* @since 2.10
673+
*/
674+
public <T extends JsonNode> T requireNonNull() {
675+
return _this();
676+
}
677+
678+
/**
679+
* @since 2.10
680+
*/
681+
public JsonNode required(String fieldName) {
682+
return _reportRequiredViolation("Node of type `%s` has no fields", getClass().getName());
683+
}
684+
685+
/**
686+
* @since 2.10
687+
*/
688+
public JsonNode required(int index) {
689+
return _reportRequiredViolation("Node of type `%s` has no indexed values", getClass().getName());
690+
}
691+
692+
/**
693+
* @since 2.10
694+
*/
695+
public JsonNode requiredAt(String pathExpr) {
696+
return requiredAt(JsonPointer.compile(pathExpr));
697+
}
698+
699+
/**
700+
* @since 2.10
701+
*/
702+
public final JsonNode requiredAt(final JsonPointer pathExpr) {
703+
JsonPointer currentExpr = pathExpr;
704+
JsonNode curr = this;
705+
706+
// Note: copied from `at()`
707+
while (true) {
708+
if (currentExpr.matches()) {
709+
return curr;
710+
}
711+
curr = curr._at(currentExpr);
712+
if (curr == null) {
713+
_reportRequiredViolation("No node at '%s' (unmatched part: '%s')",
714+
pathExpr, currentExpr);
715+
}
716+
currentExpr = currentExpr.tail();
717+
}
718+
}
719+
658720
/*
659721
/**********************************************************************
660722
/* Public API, value find / existence check methods
@@ -971,4 +1033,25 @@ public String toPrettyString() {
9711033
*/
9721034
@Override
9731035
public abstract boolean equals(Object o);
1036+
1037+
/*
1038+
/**********************************************************************
1039+
/* Helper methods, for sub-classes
1040+
/**********************************************************************
1041+
*/
1042+
1043+
// @since 2.10
1044+
@SuppressWarnings("unchecked")
1045+
protected <T extends JsonNode> T _this() {
1046+
return (T) this;
1047+
}
1048+
1049+
/**
1050+
* Helper method that throws {@link IllegalArgumentException} as a result of
1051+
* violating "required-constraint" for this node (for {@link #require() or related
1052+
* methods).
1053+
*/
1054+
protected <T> T _reportRequiredViolation(String msgTemplate, Object...args) {
1055+
throw new IllegalArgumentException(String.format(msgTemplate, args));
1056+
}
9741057
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ public JsonNode path(int index) {
126126
return MissingNode.getInstance();
127127
}
128128

129+
@Override
130+
public JsonNode required(int index) {
131+
if ((index >= 0) && (index < _children.size())) {
132+
return _children.get(index);
133+
}
134+
return _reportRequiredViolation("No value at index #%d [0, %d) of `ArrayNode`",
135+
index, _children.size());
136+
}
137+
129138
@Override
130139
public boolean equals(Comparator<JsonNode> comparator, JsonNode o)
131140
{

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,24 @@ public final JsonNode findPath(String fieldName)
6464
// Also, force (re)definition
6565
@Override public abstract int hashCode();
6666

67+
/*
68+
/**********************************************************************
69+
/* Improved required-ness checks for standard JsonNode implementations
70+
/**********************************************************************
71+
*/
72+
73+
@Override
74+
public JsonNode required(String fieldName) {
75+
return _reportRequiredViolation("Node of type `%s` has no fields",
76+
getClass().getSimpleName());
77+
}
78+
79+
@Override
80+
public JsonNode required(int index) {
81+
return _reportRequiredViolation("Node of type `%s` has no indexed values",
82+
getClass().getSimpleName());
83+
}
84+
6785
/*
6886
/**********************************************************
6987
/* Support for traversal-as-stream

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ public class BigIntegerNode
1919
private final static BigInteger MAX_INTEGER = BigInteger.valueOf(Integer.MAX_VALUE);
2020
private final static BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
2121
private final static BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
22-
22+
2323
final protected BigInteger _value;
24-
24+
2525
/*
2626
/**********************************************************
2727
/* Construction

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,18 @@ public boolean equals(Object o)
101101
return (o == this);
102102
}
103103

104+
@SuppressWarnings("unchecked")
105+
@Override
106+
public JsonNode require() {
107+
return _reportRequiredViolation("require() called on `MissingNode`");
108+
}
109+
110+
@SuppressWarnings("unchecked")
111+
@Override
112+
public JsonNode requireNonNull() {
113+
return _reportRequiredViolation("requireNonNull() called on `MissingNode`");
114+
}
115+
104116
@Override
105117
public int hashCode() {
106118
return JsonNodeType.MISSING.ordinal();

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.IOException;
44

55
import com.fasterxml.jackson.core.*;
6+
import com.fasterxml.jackson.databind.JsonNode;
67
import com.fasterxml.jackson.databind.SerializerProvider;
78

89

@@ -38,6 +39,12 @@ public JsonNodeType getNodeType() {
3839
@Override public String asText(String defaultValue) { return defaultValue; }
3940
@Override public String asText() { return "null"; }
4041

42+
@SuppressWarnings("unchecked")
43+
@Override
44+
public JsonNode requireNonNull() {
45+
return _reportRequiredViolation("requireNonNull() called on `NullNode`");
46+
}
47+
4148
// as with MissingNode, not considered number node; hence defaults are returned if provided
4249

4350
/*

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ public JsonNode path(String fieldName)
126126
return MissingNode.getInstance();
127127
}
128128

129+
@Override
130+
public JsonNode required(String fieldName) {
131+
JsonNode n = _children.get(fieldName);
132+
if (n != null) {
133+
return n;
134+
}
135+
return _reportRequiredViolation("No value for property '%s' of `ObjectNode`", fieldName);
136+
}
137+
129138
/**
130139
* Method to use for accessing all fields (with both names
131140
* and values) of this JSON Object.

src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForObject.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.*;
44

5-
65
import com.fasterxml.jackson.core.*;
76
import com.fasterxml.jackson.annotation.JsonTypeInfo;
87
import com.fasterxml.jackson.databind.*;
@@ -381,16 +380,16 @@ public void testNoGoWithExternalProperty() throws Exception
381380
public void testWithFinalClass() throws Exception
382381
{
383382
// First: type info NOT included
384-
ObjectMapper mapper = JsonMapper.builder()
383+
ObjectMapper mapper = jsonMapperBuilder()
385384
.activateDefaultTyping(NoCheckSubTypeValidator.instance,
386-
ObjectMapper.DefaultTyping.NON_FINAL)
385+
DefaultTyping.NON_FINAL)
387386
.build();
388387
assertEquals(aposToQuotes("{'name':'abc'}"),
389388
mapper.writeValueAsString(new FinalStringBean("abc")));
390389

391-
mapper = JsonMapper.builder()
390+
mapper = jsonMapperBuilder()
392391
.activateDefaultTyping(NoCheckSubTypeValidator.instance,
393-
ObjectMapper.DefaultTyping.EVERYTHING)
392+
DefaultTyping.EVERYTHING)
394393
.build();
395394
assertEquals(aposToQuotes("['"+FinalStringBean.class.getName()+"',{'name':'abc'}]"),
396395
mapper.writeValueAsString(new FinalStringBean("abc")));

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static class MyValue
6868
/**********************************************************
6969
*/
7070

71-
private final ObjectMapper MAPPER = objectMapper();
71+
private final ObjectMapper MAPPER = sharedMapper();
7272

7373
public void testSimpleObject() throws Exception
7474
{

0 commit comments

Comments
 (0)