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
15 @SuppressWarnings("serial")
16 public class JsonNodeDeserializer
17 extends BaseNodeDeserializer<JsonNode>
18 {
19
23 private final static JsonNodeDeserializer instance = new JsonNodeDeserializer();
24
25 protected JsonNodeDeserializer() {
26
27
28
29 super(JsonNode.class, null);
30 }
31
32
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
44 return instance;
45 }
46
47
52
53 @Override
54 public JsonNode getNullValue(DeserializationContext ctxt) {
55 return ctxt.getNodeFactory().nullNode();
56 }
57
58
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
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.class, true); }
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
103
104 if (p.hasToken(JsonToken.END_OBJECT)) {
105 return ctxt.getNodeFactory().objectNode();
106 }
107 return (ObjectNode) ctxt.handleUnexpectedToken(ObjectNode.class, p);
108 }
109
110
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.class, true); }
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
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
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
184 return typeDeserializer.deserializeTypedFromAny(p, ctxt);
185 }
186
187
191 @Override
192 public boolean isCachable() { return true; }
193
194 @Override
195 public Boolean supportsUpdate(DeserializationConfig config) {
196 return _supportsUpdates;
197 }
198
199
204
205
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
225 if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)) {
226
227
228
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
240
241
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) {
254 t = JsonToken.NOT_AVAILABLE;
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
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) {
308 t = JsonToken.NOT_AVAILABLE;
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
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
367 JsonToken t = p.nextToken();
368
369
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) {
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
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:
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
544
545
546
547
548
549
550
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
590
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) {
607 return nodeFactory.nullNode();
608 }
609 Class<?> type = ob.getClass();
610 if (type == byte[].class) {
611 return nodeFactory.binaryNode((byte[]) ob);
612 }
613
614 if (ob instanceof RawValue) {
615 return nodeFactory.rawValueNode((RawValue) ob);
616 }
617 if (ob instanceof JsonNode) {
618
619 return (JsonNode) ob;
620 }
621
622 return nodeFactory.pojoNode(ob);
623 }
624 }
625