Skip to content

Commit 3cd7ae3

Browse files
committed
Allow custom JsonNode implementations
Fixes FasterXML#3699
1 parent dd733c4 commit 3cd7ae3

File tree

4 files changed

+291
-1
lines changed

4 files changed

+291
-1
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ protected final static class ObjectCursor
195195
public ObjectCursor(JsonNode n, NodeCursor p)
196196
{
197197
super(JsonStreamContext.TYPE_OBJECT, p);
198-
_contents = ((ObjectNode) n).fields();
198+
if (!n.isObject()) {
199+
throw new IllegalStateException("Current node is not an object node");
200+
}
201+
_contents = n.fields();
199202
_needEntry = true;
200203
}
201204

src/test/java/com/fasterxml/jackson/databind/ObjectReaderTest.java

+23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
1818
import com.fasterxml.jackson.databind.json.JsonMapper;
1919
import com.fasterxml.jackson.databind.node.ArrayNode;
20+
import com.fasterxml.jackson.databind.node.CustomArrayNode;
21+
import com.fasterxml.jackson.databind.node.CustomObjectNode;
2022
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
2123
import com.fasterxml.jackson.databind.node.ObjectNode;
2224

@@ -532,4 +534,25 @@ private A(@JsonProperty("knownField") String knownField) {
532534
this.knownField = knownField;
533535
}
534536
}
537+
538+
// [databind#3699]: custom object node classes
539+
public void testCustomObjectNode() throws Exception
540+
{
541+
ObjectNode defaultNode = (ObjectNode) MAPPER.readTree("{\"x\": 1, \"y\": 2}");
542+
CustomObjectNode customObjectNode = new CustomObjectNode(defaultNode);
543+
Point point = MAPPER.readerFor(Point.class).readValue(customObjectNode);
544+
assertEquals(1, point.x);
545+
assertEquals(2, point.y);
546+
}
547+
548+
// [databind#3699]: custom array node classes
549+
public void testCustomArrayNode() throws Exception
550+
{
551+
ArrayNode defaultNode = (ArrayNode) MAPPER.readTree("[{\"x\": 1, \"y\": 2}]");
552+
CustomArrayNode customArrayNode = new CustomArrayNode(defaultNode);
553+
Point[] points = MAPPER.readerFor(Point[].class).readValue(customArrayNode);
554+
Point point = points[0];
555+
assertEquals(1, point.x);
556+
assertEquals(2, point.y);
557+
}
535558
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package com.fasterxml.jackson.databind.node;
2+
3+
import java.io.IOException;
4+
import java.util.Iterator;
5+
import java.util.List;
6+
7+
import com.fasterxml.jackson.core.JsonGenerator;
8+
import com.fasterxml.jackson.core.JsonPointer;
9+
import com.fasterxml.jackson.core.JsonToken;
10+
import com.fasterxml.jackson.databind.JsonNode;
11+
import com.fasterxml.jackson.databind.SerializerProvider;
12+
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
13+
14+
public class CustomArrayNode extends BaseJsonNode
15+
{
16+
private final ArrayNode _delegate;
17+
18+
public CustomArrayNode(ArrayNode delegate) {
19+
this._delegate = delegate;
20+
}
21+
22+
@Override
23+
public boolean isArray() {
24+
return true;
25+
}
26+
27+
@Override
28+
public int size() {
29+
return _delegate.size();
30+
}
31+
32+
@Override
33+
public Iterator<JsonNode> elements() {
34+
return _delegate.elements();
35+
}
36+
37+
@Override
38+
public JsonToken asToken() {
39+
return _delegate.asToken();
40+
}
41+
42+
@Override
43+
public void serialize(JsonGenerator g, SerializerProvider ctxt) throws IOException {
44+
_delegate.serialize(g, ctxt);
45+
}
46+
47+
@Override
48+
public void serializeWithType(JsonGenerator g, SerializerProvider ctxt, TypeSerializer typeSer) throws IOException {
49+
_delegate.serializeWithType(g, ctxt, typeSer);
50+
}
51+
52+
@Override
53+
public <T extends JsonNode> T deepCopy() {
54+
return (T) _delegate.deepCopy();
55+
}
56+
57+
@Override
58+
public JsonNode get(int index) {
59+
return _delegate.get(index);
60+
}
61+
62+
@Override
63+
public JsonNode path(String fieldName) {
64+
return _delegate.path(fieldName);
65+
}
66+
67+
@Override
68+
public JsonNode path(int index) {
69+
return _delegate.path(index);
70+
}
71+
72+
@Override
73+
protected JsonNode _at(JsonPointer ptr) {
74+
return _delegate.get(ptr.getMatchingIndex());
75+
}
76+
77+
@Override
78+
public JsonNodeType getNodeType() {
79+
return _delegate.getNodeType();
80+
}
81+
82+
@Override
83+
public String asText() {
84+
return _delegate.asText();
85+
}
86+
87+
@Override
88+
public JsonNode findValue(String fieldName) {
89+
return _delegate.findValue(fieldName);
90+
}
91+
92+
@Override
93+
public JsonNode findParent(String fieldName) {
94+
return _delegate.findParent(fieldName);
95+
}
96+
97+
@Override
98+
public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) {
99+
return _delegate.findValues(fieldName, foundSoFar);
100+
}
101+
102+
@Override
103+
public List<String> findValuesAsText(String fieldName, List<String> foundSoFar) {
104+
return _delegate.findValuesAsText(fieldName, foundSoFar);
105+
}
106+
107+
@Override
108+
public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) {
109+
return _delegate.findParents(fieldName, foundSoFar);
110+
}
111+
112+
@Override
113+
public boolean equals(Object o) {
114+
if (o == this) {
115+
return true;
116+
}
117+
if (!(o instanceof CustomArrayNode)) {
118+
return false;
119+
}
120+
CustomArrayNode other = (CustomArrayNode) o;
121+
return this._delegate.equals(other._delegate);
122+
}
123+
124+
@Override
125+
public int hashCode() {
126+
return _delegate.hashCode();
127+
}
128+
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package com.fasterxml.jackson.databind.node;
2+
3+
import java.io.IOException;
4+
import java.util.Iterator;
5+
import java.util.List;
6+
import java.util.Map.Entry;
7+
8+
import com.fasterxml.jackson.core.JsonGenerator;
9+
import com.fasterxml.jackson.core.JsonPointer;
10+
import com.fasterxml.jackson.core.JsonToken;
11+
import com.fasterxml.jackson.databind.JsonNode;
12+
import com.fasterxml.jackson.databind.SerializerProvider;
13+
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
14+
15+
public class CustomObjectNode extends BaseJsonNode
16+
{
17+
private final ObjectNode _delegate;
18+
19+
public CustomObjectNode(ObjectNode delegate) {
20+
this._delegate = delegate;
21+
}
22+
23+
@Override
24+
public boolean isObject() {
25+
return true;
26+
}
27+
28+
@Override
29+
public int size() {
30+
return _delegate.size();
31+
}
32+
33+
@Override
34+
public Iterator<Entry<String, JsonNode>> fields() {
35+
return _delegate.fields();
36+
}
37+
38+
@Override
39+
public Iterator<JsonNode> elements() {
40+
return _delegate.elements();
41+
}
42+
43+
@Override
44+
public JsonToken asToken() {
45+
return _delegate.asToken();
46+
}
47+
48+
@Override
49+
public void serialize(JsonGenerator g, SerializerProvider ctxt) throws IOException {
50+
_delegate.serialize(g, ctxt);
51+
}
52+
53+
@Override
54+
public void serializeWithType(JsonGenerator g, SerializerProvider ctxt, TypeSerializer typeSer) throws IOException {
55+
_delegate.serializeWithType(g, ctxt, typeSer);
56+
}
57+
58+
@Override
59+
public <T extends JsonNode> T deepCopy() {
60+
return (T) _delegate.deepCopy();
61+
}
62+
63+
@Override
64+
public JsonNode get(int index) {
65+
return _delegate.get(index);
66+
}
67+
68+
@Override
69+
public JsonNode path(String fieldName) {
70+
return _delegate.path(fieldName);
71+
}
72+
73+
@Override
74+
public JsonNode path(int index) {
75+
return _delegate.path(index);
76+
}
77+
78+
@Override
79+
protected JsonNode _at(JsonPointer ptr) {
80+
return _delegate.get(ptr.getMatchingProperty());
81+
}
82+
83+
@Override
84+
public JsonNodeType getNodeType() {
85+
return _delegate.getNodeType();
86+
}
87+
88+
@Override
89+
public String asText() {
90+
return _delegate.asText();
91+
}
92+
93+
@Override
94+
public JsonNode findValue(String fieldName) {
95+
return _delegate.findValue(fieldName);
96+
}
97+
98+
@Override
99+
public JsonNode findParent(String fieldName) {
100+
return _delegate.findParent(fieldName);
101+
}
102+
103+
@Override
104+
public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) {
105+
return _delegate.findValues(fieldName, foundSoFar);
106+
}
107+
108+
@Override
109+
public List<String> findValuesAsText(String fieldName, List<String> foundSoFar) {
110+
return _delegate.findValuesAsText(fieldName, foundSoFar);
111+
}
112+
113+
@Override
114+
public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) {
115+
return _delegate.findParents(fieldName, foundSoFar);
116+
}
117+
118+
@Override
119+
public boolean equals(Object o) {
120+
if (o == this) {
121+
return true;
122+
}
123+
if (!(o instanceof CustomObjectNode)) {
124+
return false;
125+
}
126+
CustomObjectNode other = (CustomObjectNode) o;
127+
return this._delegate.equals(other._delegate);
128+
}
129+
130+
@Override
131+
public int hashCode() {
132+
return _delegate.hashCode();
133+
}
134+
135+
}

0 commit comments

Comments
 (0)