1 package com.fasterxml.jackson.databind.deser.std;
2
3 import java.io.IOException;
4
5 import com.fasterxml.jackson.core.*;
6 import com.fasterxml.jackson.databind.*;
7 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
8 import com.fasterxml.jackson.databind.node.*;
9 import com.fasterxml.jackson.databind.util.RawValue;
10
11 /**
12  * Deserializer that can build instances of {@link JsonNode} from any
13  * JSON content, using appropriate {@link JsonNode} type.
14  */

15 @SuppressWarnings("serial")
16 public class JsonNodeDeserializer
17     extends BaseNodeDeserializer<JsonNode>
18 {
19     /**
20      * Singleton instance of generic deserializer for {@link JsonNode}.
21      * Only used for types other than JSON Object and Array.
22      */

23     private final static JsonNodeDeserializer instance = new JsonNodeDeserializer();
24
25     protected JsonNodeDeserializer() {
26         // `null` means that explicit "merge" is honored and may or may not work, but
27         // that per-type and global defaults do not enable merging. This because
28         // some node types (Object, Array) do support, others don't.
29         super(JsonNode.classnull);
30     }
31
32     /**
33      * Factory method for accessing deserializer for specific node type
34      */

35     public static JsonDeserializer<? extends JsonNode> getDeserializer(Class<?> nodeClass)
36     {
37         if (nodeClass == ObjectNode.class) {
38             return ObjectDeserializer.getInstance();
39         }
40         if (nodeClass == ArrayNode.class) {
41             return ArrayDeserializer.getInstance();
42         }
43         // For others, generic one works fine
44         return instance;
45     }
46     
47     /*
48     /**********************************************************
49     /* Actual deserializer implementations
50     /**********************************************************
51      */

52
53     @Override
54     public JsonNode getNullValue(DeserializationContext ctxt) {
55         return ctxt.getNodeFactory().nullNode();
56     }
57
58     /**
59      * Implementation that will produce types of any JSON nodes; not just one
60      * deserializer is registered to handle (in case of more specialized handler).
61      * Overridden by typed sub-classes for more thorough checking
62      */

63     @Override
64     public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
65     {
66         switch (p.currentTokenId()) {
67         case JsonTokenId.ID_START_OBJECT:
68             return deserializeObject(p, ctxt, ctxt.getNodeFactory());
69         case JsonTokenId.ID_START_ARRAY:
70             return deserializeArray(p, ctxt, ctxt.getNodeFactory());
71         default:
72         }
73         return deserializeAny(p, ctxt, ctxt.getNodeFactory());
74     }
75
76     /*
77     /**********************************************************
78     /* Specific instances for more accurate types
79     /**********************************************************
80      */

81
82     final static class ObjectDeserializer
83         extends BaseNodeDeserializer<ObjectNode>
84     {
85         private static final long serialVersionUID = 1L;
86
87         protected final static ObjectDeserializer _instance = new ObjectDeserializer();
88
89         protected ObjectDeserializer() { super(ObjectNode.classtrue); }
90
91         public static ObjectDeserializer getInstance() { return _instance; }
92
93         @Override
94         public ObjectNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
95         {
96             if (p.isExpectedStartObjectToken()) {
97                 return deserializeObject(p, ctxt, ctxt.getNodeFactory());
98             }
99             if (p.hasToken(JsonToken.FIELD_NAME)) {
100                 return deserializeObjectAtName(p, ctxt, ctxt.getNodeFactory());
101             }
102             // 23-Sep-2015, tatu: Ugh. We may also be given END_OBJECT (similar to FIELD_NAME),
103             //    if caller has advanced to the first token of Object, but for empty Object
104             if (p.hasToken(JsonToken.END_OBJECT)) {
105                 return ctxt.getNodeFactory().objectNode();
106             }
107             return (ObjectNode) ctxt.handleUnexpectedToken(ObjectNode.class, p);
108          }
109
110         /**
111          * Variant needed to support both root-level `updateValue()` and merging.
112          *
113          * @since 2.9
114          */

115         @Override
116         public ObjectNode deserialize(JsonParser p, DeserializationContext ctxt,
117                 ObjectNode node) throws IOException
118         {
119             if (p.isExpectedStartObjectToken() || p.hasToken(JsonToken.FIELD_NAME)) {
120                 return (ObjectNode) updateObject(p, ctxt, (ObjectNode) node);
121             }
122             return (ObjectNode) ctxt.handleUnexpectedToken(ObjectNode.class, p);
123         }
124     }
125
126     final static class ArrayDeserializer
127         extends BaseNodeDeserializer<ArrayNode>
128     {
129         private static final long serialVersionUID = 1L;
130
131         protected final static ArrayDeserializer _instance = new ArrayDeserializer();
132
133         protected ArrayDeserializer() { super(ArrayNode.classtrue); }
134
135         public static ArrayDeserializer getInstance() { return _instance; }
136
137         @Override
138         public ArrayNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
139         {
140             if (p.isExpectedStartArrayToken()) {
141                 return deserializeArray(p, ctxt, ctxt.getNodeFactory());
142             }
143             return (ArrayNode) ctxt.handleUnexpectedToken(ArrayNode.class, p);
144         }
145
146         /**
147          * Variant needed to support both root-level `updateValue()` and merging.
148          *
149          * @since 2.9
150          */

151         @Override
152         public ArrayNode deserialize(JsonParser p, DeserializationContext ctxt,
153                 ArrayNode node) throws IOException
154         {
155             if (p.isExpectedStartArrayToken()) {
156                 return (ArrayNode) updateArray(p, ctxt, (ArrayNode) node);
157             }
158             return (ArrayNode) ctxt.handleUnexpectedToken(ArrayNode.class, p);
159         }
160     }
161 }
162
163 /**
164  * Base class for all actual {@link JsonNode} deserializer
165  * implementations
166  */

167 @SuppressWarnings("serial")
168 abstract class BaseNodeDeserializer<T extends JsonNode>
169     extends StdDeserializer<T>
170 {
171     protected final Boolean _supportsUpdates;
172
173     public BaseNodeDeserializer(Class<T> vc, Boolean supportsUpdates) {
174         super(vc);
175         _supportsUpdates = supportsUpdates;
176     }
177
178     @Override
179     public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
180             TypeDeserializer typeDeserializer)
181         throws IOException
182     {
183         // Output can be as JSON Object, Array or scalar: no way to know a priori:
184         return typeDeserializer.deserializeTypedFromAny(p, ctxt);
185     }
186
187     /* 07-Nov-2014, tatu: When investigating [databind#604], realized that it makes
188      *   sense to also mark this is cachable, since lookup not exactly free, and
189      *   since it's not uncommon to "read anything"
190      */

191     @Override
192     public boolean isCachable() { return true; }
193
194     @Override // since 2.9
195     public Boolean supportsUpdate(DeserializationConfig config) {
196         return _supportsUpdates;
197     }
198
199     /*
200     /**********************************************************
201     /* Overridable methods
202     /**********************************************************
203      */

204
205     /**
206      * Method called when there is a duplicate value for a field.
207      * By default we don't care, and the last value is used.
208      * Can be overridden to provide alternate handling, such as throwing
209      * an exception, or choosing different strategy for combining values
210      * or choosing which one to keep.
211      *
212      * @param fieldName Name of the field for which duplicate value was found
213      * @param objectNode Object node that contains values
214      * @param oldValue Value that existed for the object node before newValue
215      *   was added
216      * @param newValue Newly added value just added to the object node
217      */

218     protected void _handleDuplicateField(JsonParser p, DeserializationContext ctxt,
219             JsonNodeFactory nodeFactory,
220             String fieldName, ObjectNode objectNode,
221             JsonNode oldValue, JsonNode newValue)
222         throws JsonProcessingException
223     {
224         // [databind#237]: Report an error if asked to do so:
225         if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)) {
226             // 11-Sep-2019, tatu: Can not pass "property name" because we may be
227             //    missing enclosing JSON content context...
228 // ctxt.reportPropertyInputMismatch(JsonNode.class, fieldName,
229             ctxt.reportInputMismatch(JsonNode.class,
230 "Duplicate field '%s' for `ObjectNode`: not allowed when `DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY` enabled",
231                     fieldName);
232         }
233     }
234
235     /*
236     /**********************************************************
237     /* Helper methods
238     /**********************************************************
239      */

240
241     /**
242      * Method called to deserialize Object node instance when there is no existing
243      * node to modify.
244      */

245     protected final ObjectNode deserializeObject(JsonParser p, DeserializationContext ctxt,
246             final JsonNodeFactory nodeFactory) throws IOException
247     {
248         final ObjectNode node = nodeFactory.objectNode();
249         String key = p.nextFieldName();
250         for (; key != null; key = p.nextFieldName()) {
251             JsonNode value;
252             JsonToken t = p.nextToken();
253             if (t == null) { // can this ever occur?
254                 t = JsonToken.NOT_AVAILABLE; // can this ever occur?
255             }
256             switch (t.id()) {
257             case JsonTokenId.ID_START_OBJECT:
258                 value = deserializeObject(p, ctxt, nodeFactory);
259                 break;
260             case JsonTokenId.ID_START_ARRAY:
261                 value = deserializeArray(p, ctxt, nodeFactory);
262                 break;
263             case JsonTokenId.ID_EMBEDDED_OBJECT:
264                 value = _fromEmbedded(p, ctxt, nodeFactory);
265                 break;
266             case JsonTokenId.ID_STRING:
267                 value = nodeFactory.textNode(p.getText());
268                 break;
269             case JsonTokenId.ID_NUMBER_INT:
270                 value = _fromInt(p, ctxt, nodeFactory);
271                 break;
272             case JsonTokenId.ID_TRUE:
273                 value = nodeFactory.booleanNode(true);
274                 break;
275             case JsonTokenId.ID_FALSE:
276                 value = nodeFactory.booleanNode(false);
277                 break;
278             case JsonTokenId.ID_NULL:
279                 value = nodeFactory.nullNode();
280                 break;
281             default:
282                 value = deserializeAny(p, ctxt, nodeFactory);
283             }
284             JsonNode old = node.replace(key, value);
285             if (old != null) {
286                 _handleDuplicateField(p, ctxt, nodeFactory,
287                         key, node, old, value);
288             }
289         }
290         return node;
291     }
292
293     /**
294      * Alternate deserialization method used when parser already points to first
295      * FIELD_NAME and not START_OBJECT.
296      *
297      * @since 2.9
298      */

299     protected final ObjectNode deserializeObjectAtName(JsonParser p, DeserializationContext ctxt,
300             final JsonNodeFactory nodeFactory) throws IOException
301     {
302         final ObjectNode node = nodeFactory.objectNode();
303         String key = p.getCurrentName();
304         for (; key != null; key = p.nextFieldName()) {
305             JsonNode value;
306             JsonToken t = p.nextToken();
307             if (t == null) { // can this ever occur?
308                 t = JsonToken.NOT_AVAILABLE; // can this ever occur?
309             }
310             switch (t.id()) {
311             case JsonTokenId.ID_START_OBJECT:
312                 value = deserializeObject(p, ctxt, nodeFactory);
313                 break;
314             case JsonTokenId.ID_START_ARRAY:
315                 value = deserializeArray(p, ctxt, nodeFactory);
316                 break;
317             case JsonTokenId.ID_EMBEDDED_OBJECT:
318                 value = _fromEmbedded(p, ctxt, nodeFactory);
319                 break;
320             case JsonTokenId.ID_STRING:
321                 value = nodeFactory.textNode(p.getText());
322                 break;
323             case JsonTokenId.ID_NUMBER_INT:
324                 value = _fromInt(p, ctxt, nodeFactory);
325                 break;
326             case JsonTokenId.ID_TRUE:
327                 value = nodeFactory.booleanNode(true);
328                 break;
329             case JsonTokenId.ID_FALSE:
330                 value = nodeFactory.booleanNode(false);
331                 break;
332             case JsonTokenId.ID_NULL:
333                 value = nodeFactory.nullNode();
334                 break;
335             default:
336                 value = deserializeAny(p, ctxt, nodeFactory);
337             }
338             JsonNode old = node.replace(key, value);
339             if (old != null) {
340                 _handleDuplicateField(p, ctxt, nodeFactory,
341                         key, node, old, value);
342             }
343         }
344         return node;
345     }
346     
347     /**
348      * Alternate deserialization method that is to update existing {@link ObjectNode}
349      * if possible.
350      *
351      * @since 2.9
352      */

353     protected final JsonNode updateObject(JsonParser p, DeserializationContext ctxt,
354         final ObjectNode node) throws IOException
355     {
356         String key;
357         if (p.isExpectedStartObjectToken()) {
358             key = p.nextFieldName();
359         } else {
360             if (!p.hasToken(JsonToken.FIELD_NAME)) {
361                 return deserialize(p, ctxt);
362             }
363             key = p.getCurrentName();
364         }
365         for (; key != null; key = p.nextFieldName()) {
366             // If not, fall through to regular handling
367             JsonToken t = p.nextToken();
368
369             // First: see if we can merge things:
370             JsonNode old = node.get(key);
371             if (old != null) {
372                 if (old instanceof ObjectNode) {
373                     JsonNode newValue = updateObject(p, ctxt, (ObjectNode) old);
374                     if (newValue != old) {
375                         node.set(key, newValue);
376                     }
377                     continue;
378                 }
379                 if (old instanceof ArrayNode) {
380                     JsonNode newValue = updateArray(p, ctxt, (ArrayNode) old);
381                     if (newValue != old) {
382                         node.set(key, newValue);
383                     }
384                     continue;
385                 }
386             }
387             if (t == null) { // can this ever occur?
388                 t = JsonToken.NOT_AVAILABLE;
389             }
390             JsonNode value;
391             JsonNodeFactory nodeFactory = ctxt.getNodeFactory();
392             switch (t.id()) {
393             case JsonTokenId.ID_START_OBJECT:
394                 value = deserializeObject(p, ctxt, nodeFactory);
395                 break;
396             case JsonTokenId.ID_START_ARRAY:
397                 value = deserializeArray(p, ctxt, nodeFactory);
398                 break;
399             case JsonTokenId.ID_EMBEDDED_OBJECT:
400                 value = _fromEmbedded(p, ctxt, nodeFactory);
401                 break;
402             case JsonTokenId.ID_STRING:
403                 value = nodeFactory.textNode(p.getText());
404                 break;
405             case JsonTokenId.ID_NUMBER_INT:
406                 value = _fromInt(p, ctxt, nodeFactory);
407                 break;
408             case JsonTokenId.ID_TRUE:
409                 value = nodeFactory.booleanNode(true);
410                 break;
411             case JsonTokenId.ID_FALSE:
412                 value = nodeFactory.booleanNode(false);
413                 break;
414             case JsonTokenId.ID_NULL:
415                 value = nodeFactory.nullNode();
416                 break;
417             default:
418                 value = deserializeAny(p, ctxt, nodeFactory);
419             }
420             if (old != null) {
421                 _handleDuplicateField(p, ctxt, nodeFactory,
422                         key, node, old, value);
423             }
424             node.set(key, value);
425         }
426         return node;
427     }
428
429     protected final ArrayNode deserializeArray(JsonParser p, DeserializationContext ctxt,
430             final JsonNodeFactory nodeFactory) throws IOException
431     {
432         ArrayNode node = nodeFactory.arrayNode();
433         while (true) {
434             JsonToken t = p.nextToken();
435             switch (t.id()) {
436             case JsonTokenId.ID_START_OBJECT:
437                 node.add(deserializeObject(p, ctxt, nodeFactory));
438                 break;
439             case JsonTokenId.ID_START_ARRAY:
440                 node.add(deserializeArray(p, ctxt, nodeFactory));
441                 break;
442             case JsonTokenId.ID_END_ARRAY:
443                 return node;
444             case JsonTokenId.ID_EMBEDDED_OBJECT:
445                 node.add(_fromEmbedded(p, ctxt, nodeFactory));
446                 break;
447             case JsonTokenId.ID_STRING:
448                 node.add(nodeFactory.textNode(p.getText()));
449                 break;
450             case JsonTokenId.ID_NUMBER_INT:
451                 node.add(_fromInt(p, ctxt, nodeFactory));
452                 break;
453             case JsonTokenId.ID_TRUE:
454                 node.add(nodeFactory.booleanNode(true));
455                 break;
456             case JsonTokenId.ID_FALSE:
457                 node.add(nodeFactory.booleanNode(false));
458                 break;
459             case JsonTokenId.ID_NULL:
460                 node.add(nodeFactory.nullNode());
461                 break;
462             default:
463                 node.add(deserializeAny(p, ctxt, nodeFactory));
464                 break;
465             }
466         }
467     }
468
469     /**
470      * Alternate deserialization method that is to update existing {@link ObjectNode}
471      * if possible.
472      *
473      * @since 2.9
474      */

475     protected final JsonNode updateArray(JsonParser p, DeserializationContext ctxt,
476         final ArrayNode node) throws IOException
477     {
478         final JsonNodeFactory nodeFactory = ctxt.getNodeFactory();
479         while (true) {
480             JsonToken t = p.nextToken();
481             switch (t.id()) {
482             case JsonTokenId.ID_START_OBJECT:
483                 node.add(deserializeObject(p, ctxt, nodeFactory));
484                 break;
485             case JsonTokenId.ID_START_ARRAY:
486                 node.add(deserializeArray(p, ctxt, nodeFactory));
487                 break;
488             case JsonTokenId.ID_END_ARRAY:
489                 return node;
490             case JsonTokenId.ID_EMBEDDED_OBJECT:
491                 node.add(_fromEmbedded(p, ctxt, nodeFactory));
492                 break;
493             case JsonTokenId.ID_STRING:
494                 node.add(nodeFactory.textNode(p.getText()));
495                 break;
496             case JsonTokenId.ID_NUMBER_INT:
497                 node.add(_fromInt(p, ctxt, nodeFactory));
498                 break;
499             case JsonTokenId.ID_TRUE:
500                 node.add(nodeFactory.booleanNode(true));
501                 break;
502             case JsonTokenId.ID_FALSE:
503                 node.add(nodeFactory.booleanNode(false));
504                 break;
505             case JsonTokenId.ID_NULL:
506                 node.add(nodeFactory.nullNode());
507                 break;
508             default:
509                 node.add(deserializeAny(p, ctxt, nodeFactory));
510                 break;
511             }
512         }
513     }
514
515     protected final JsonNode deserializeAny(JsonParser p, DeserializationContext ctxt,
516             final JsonNodeFactory nodeFactory) throws IOException
517     {
518         switch (p.currentTokenId()) {
519         case JsonTokenId.ID_END_OBJECT: // for empty JSON Objects we may point to this?
520             return nodeFactory.objectNode();
521         case JsonTokenId.ID_FIELD_NAME:
522             return deserializeObjectAtName(p, ctxt, nodeFactory);
523         case JsonTokenId.ID_EMBEDDED_OBJECT:
524             return _fromEmbedded(p, ctxt, nodeFactory);
525         case JsonTokenId.ID_STRING:
526             return nodeFactory.textNode(p.getText());
527         case JsonTokenId.ID_NUMBER_INT:
528             return _fromInt(p, ctxt, nodeFactory);
529         case JsonTokenId.ID_NUMBER_FLOAT:
530             return _fromFloat(p, ctxt, nodeFactory);
531         case JsonTokenId.ID_TRUE:
532             return nodeFactory.booleanNode(true);
533         case JsonTokenId.ID_FALSE:
534             return nodeFactory.booleanNode(false);
535         case JsonTokenId.ID_NULL:
536             return nodeFactory.nullNode();
537
538             /* Caller checks for these, should not get here ever
539         case JsonTokenId.ID_START_OBJECT:
540             return deserializeObject(p, ctxt, nodeFactory);
541         case JsonTokenId.ID_START_ARRAY:
542             return deserializeArray(p, ctxt, nodeFactory);
543             */

544
545             
546             // These states cannot be mapped; input stream is
547             // off by an event or two
548
549         //case END_OBJECT:
550         //case END_ARRAY:
551         default:
552         }
553         return (JsonNode) ctxt.handleUnexpectedToken(handledType(), p);
554     }
555
556     protected final JsonNode _fromInt(JsonParser p, DeserializationContext ctxt,
557             JsonNodeFactory nodeFactory) throws IOException
558     {
559         JsonParser.NumberType nt;
560         int feats = ctxt.getDeserializationFeatures();
561         if ((feats & F_MASK_INT_COERCIONS) != 0) {
562             if (DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.enabledIn(feats)) {
563                 nt = JsonParser.NumberType.BIG_INTEGER;
564             } else if (DeserializationFeature.USE_LONG_FOR_INTS.enabledIn(feats)) {
565                 nt = JsonParser.NumberType.LONG;
566             } else {
567                 nt = p.getNumberType();
568             }
569         } else {
570             nt = p.getNumberType();
571         }
572         if (nt == JsonParser.NumberType.INT) {
573             return nodeFactory.numberNode(p.getIntValue());
574         }
575         if (nt == JsonParser.NumberType.LONG) {
576             return nodeFactory.numberNode(p.getLongValue());
577         }
578         return nodeFactory.numberNode(p.getBigIntegerValue());
579     }
580
581     protected final JsonNode _fromFloat(JsonParser p, DeserializationContext ctxt,
582             final JsonNodeFactory nodeFactory) throws IOException
583     {
584         JsonParser.NumberType nt = p.getNumberType();
585         if (nt == JsonParser.NumberType.BIG_DECIMAL) {
586             return nodeFactory.numberNode(p.getDecimalValue());
587         }
588         if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
589             // 20-May-2016, tatu: As per [databind#1028], need to be careful
590             //   (note: JDK 1.8 would have `Double.isFinite()`)
591             if (p.isNaN()) {
592                 return nodeFactory.numberNode(p.getDoubleValue());
593             }
594             return nodeFactory.numberNode(p.getDecimalValue());
595         }
596         if (nt == JsonParser.NumberType.FLOAT) {
597             return nodeFactory.numberNode(p.getFloatValue());
598         }
599         return nodeFactory.numberNode(p.getDoubleValue());
600     }
601
602     protected final JsonNode _fromEmbedded(JsonParser p, DeserializationContext ctxt,
603             JsonNodeFactory nodeFactory) throws IOException
604     {
605         Object ob = p.getEmbeddedObject();
606         if (ob == null) { // should this occur?
607             return nodeFactory.nullNode();
608         }
609         Class<?> type = ob.getClass();
610         if (type == byte[].class) { // most common special case
611             return nodeFactory.binaryNode((byte[]) ob);
612         }
613         // [databind#743]: Don't forget RawValue
614         if (ob instanceof RawValue) {
615             return nodeFactory.rawValueNode((RawValue) ob);
616         }
617         if (ob instanceof JsonNode) {
618             // [databind#433]: but could also be a JsonNode hiding in there!
619             return (JsonNode) ob;
620         }
621         // any other special handling needed?
622         return nodeFactory.pojoNode(ob);
623     }
624 }
625