7
7
8
8
import com .fasterxml .jackson .core .*;
9
9
import com .fasterxml .jackson .core .type .WritableTypeId ;
10
+
10
11
import com .fasterxml .jackson .databind .*;
11
12
import com .fasterxml .jackson .databind .cfg .JsonNodeFeature ;
12
13
import com .fasterxml .jackson .databind .jsontype .TypeSerializer ;
@@ -23,6 +24,12 @@ public class ObjectNode
23
24
{
24
25
private static final long serialVersionUID = 1L ; // since 2.10
25
26
27
+ /**
28
+ * Constant that defines maximum {@code JsonPointer} element index we
29
+ * use for inserts.
30
+ */
31
+ protected final static int MAX_ELEMENT_INDEX_FOR_INSERT = 9999 ;
32
+
26
33
// Note: LinkedHashMap for backwards compatibility
27
34
protected final Map <String , JsonNode > _children ;
28
35
@@ -61,19 +68,103 @@ public ObjectNode deepCopy()
61
68
}
62
69
63
70
@ Override
64
- protected ObjectNode _withObjectCreatePath (JsonPointer origPtr ,
71
+ protected ObjectNode _withObject (JsonPointer origPtr ,
65
72
JsonPointer currentPtr ,
66
73
OverwriteMode overwriteMode , boolean preferIndex )
67
74
{
68
- ObjectNode currentNode = this ;
69
- while (!currentPtr .matches ()) {
70
- // Should we try to build Arrays? For now, nope.
71
- currentNode = currentNode .putObject (currentPtr .getMatchingProperty ());
72
- currentPtr = currentPtr .tail ();
75
+ if (currentPtr .matches ()) {
76
+ return this ;
77
+ }
78
+
79
+ JsonNode n = _at (currentPtr );
80
+
81
+ // If there's a path, follow it
82
+ if ((n != null ) && (n instanceof BaseJsonNode )) {
83
+ ObjectNode found = ((BaseJsonNode ) n )._withObject (origPtr , currentPtr .tail (),
84
+ overwriteMode , preferIndex );
85
+ if (found != null ) {
86
+ return found ;
87
+ }
88
+ // Ok no; must replace if allowed to
89
+ if (!_withObjectMayReplace (n , overwriteMode )) {
90
+ return _reportWrongNodeType (
91
+ "Cannot replace `JsonNode` of type `%s` for property \" %s\" in JSON Pointer \" %s\" (mode `OverwriteMode.%s`)" ,
92
+ n .getClass ().getName (), currentPtr .getMatchingProperty (),
93
+ origPtr , overwriteMode );
94
+ }
95
+ }
96
+ // Either way; must replace or add a new property
97
+ return _withObjectAddTailProperty (currentPtr , preferIndex , this );
98
+ }
99
+
100
+ protected ObjectNode _withObjectAddTailProperty (JsonPointer tail , boolean preferIndex ,
101
+ ObjectNode currObject )
102
+ {
103
+ final String propName = tail .getMatchingProperty ();
104
+ tail = tail .tail ();
105
+
106
+ // First: did we complete traversal? If so, easy, we got our result
107
+ if (tail .matches ()) {
108
+ return currObject .putObject (propName );
109
+ }
110
+
111
+ // Otherwise, do we want Array or Object
112
+ if (_withObjectChooseArray (tail , preferIndex )) { // array!
113
+ return _withObjectAddTailElement (tail , preferIndex ,
114
+ currObject .putArray (propName ));
73
115
}
74
- return currentNode ;
116
+ return _withObjectAddTailProperty (tail , preferIndex ,
117
+ currObject .putObject (propName ));
75
118
}
76
119
120
+ protected ObjectNode _withObjectAddTailElement (JsonPointer tail , boolean preferIndex ,
121
+ ArrayNode currArray )
122
+ {
123
+ final int index = tail .getMatchingIndex ();
124
+ tail = tail .tail ();
125
+
126
+ // First: did we complete traversal? If so, easy, we got our result
127
+ if (tail .matches ()) {
128
+ ObjectNode result = currArray .objectNode ();
129
+ _withObjectSetArrayElement (currArray , index , result );
130
+ return result ;
131
+ }
132
+
133
+ // Otherwise, do we want Array or Object
134
+ if (_withObjectChooseArray (tail , preferIndex )) { // array!
135
+ ArrayNode next = currArray .arrayNode ();
136
+ _withObjectSetArrayElement (currArray , index , next );
137
+ return _withObjectAddTailElement (tail , preferIndex , next );
138
+ }
139
+ ObjectNode next = currArray .objectNode ();
140
+ _withObjectSetArrayElement (currArray , index , next );
141
+ return _withObjectAddTailProperty (tail , preferIndex , next );
142
+ }
143
+
144
+ protected boolean _withObjectChooseArray (JsonPointer ptr , boolean preferIndex )
145
+ {
146
+ if (preferIndex ) {
147
+ final int ix = ptr .getMatchingIndex ();
148
+ if (ix >= 0 ) {
149
+ // 27-Jul-2022, tatu: Let's make it less likely anyone OOMs by
150
+ // humongous index...
151
+ if (ix <= MAX_ELEMENT_INDEX_FOR_INSERT ) {
152
+ return true ;
153
+ }
154
+ _reportWrongNodeOperation ("Too big Array index (%d; max %d) to use for insert with `JsonPointer`" ,
155
+ ix , MAX_ELEMENT_INDEX_FOR_INSERT , ptr );
156
+ }
157
+ }
158
+ return false ;
159
+ }
160
+
161
+ protected void _withObjectSetArrayElement (ArrayNode array , int index , JsonNode value ) {
162
+ while (index >= array .size ()) {
163
+ array .addNull ();
164
+ }
165
+ array .set (index , value );
166
+ }
167
+
77
168
/*
78
169
/**********************************************************
79
170
/* Overrides for JsonSerializable.Base
0 commit comments