1 package edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind; 2 3 import java.io.IOException; 4 import java.math.BigDecimal; 5 import java.math.BigInteger; 6 import java.util.*; 7 8 import edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.core.*; 9 import edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind.node.JsonNodeType; 10 import edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind.node.MissingNode; 11 import edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind.util.ClassUtil; 12 13 /** 14 * Base class for all JSON nodes, which form the basis of JSON 15 * Tree Model that Jackson implements. 16 * One way to think of these nodes is to consider them 17 * similar to DOM nodes in XML DOM trees. 18 *<p> 19 * As a general design rule, most accessors ("getters") are included 20 * in this base class, to allow for traversing structure without 21 * type casts. Most mutators, however, need to be accessed through 22 * specific sub-classes (such as <code>ObjectNode</code> 23 * and <code>ArrayNode</code>). 24 * This seems sensible because proper type 25 * information is generally available when building or modifying 26 * trees, but less often when reading a tree (newly built from 27 * parsed JSON content). 28 *<p> 29 * Actual concrete sub-classes can be found from package 30 * {@link edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind.node}. 31 *<p> 32 * Note that it is possible to "read" from nodes, using 33 * method {@link TreeNode#traverse(ObjectCodec)}, which will result in 34 * a {@link JsonParser} being constructed. This can be used for (relatively) 35 * efficient conversations between different representations; and it is what 36 * core databind uses for methods like {@link ObjectMapper#treeToValue(TreeNode, Class)} 37 * and {@link ObjectMapper#treeAsTokens(TreeNode)} 38 */ 39 public abstract class JsonNode 40 extends JsonSerializable.Base // i.e. implements JsonSerializable 41 implements TreeNode, Iterable<JsonNode> 42 { 43 /* 44 /********************************************************** 45 /* Construction, related 46 /********************************************************** 47 */ 48 49 protected JsonNode() { } 50 51 /** 52 * Method that can be called to get a node that is guaranteed 53 * not to allow changing of this node through mutators on 54 * this node or any of its children. 55 * This means it can either make a copy of this node (and all 56 * mutable children and grand children nodes), or node itself 57 * if it is immutable. 58 *<p> 59 * Note: return type is guaranteed to have same type as the 60 * node method is called on; which is why method is declared 61 * with local generic type. 62 * 63 * @since 2.0 64 * 65 * @return Node that is either a copy of this node (and all non-leaf 66 * children); or, for immutable leaf nodes, node itself. 67 */ 68 public abstract <T extends JsonNode> T deepCopy(); 69 70 /* 71 /********************************************************** 72 /* TreeNode implementation 73 /********************************************************** 74 */ 75 76 // public abstract JsonToken asToken(); 77 // public abstract JsonToken traverse(); 78 // public abstract JsonToken traverse(ObjectCodec codec); 79 // public abstract JsonParser.NumberType numberType(); 80 81 @Override 82 public int size() { return 0; } 83 84 /** 85 * Convenience method that is functionally same as: 86 *<pre> 87 * size() == 0 88 *</pre> 89 * for all node types. 90 * 91 * @since 2.10 92 */ 93 public boolean isEmpty() { return size() == 0; } 94 95 @Override 96 public final boolean isValueNode() 97 { 98 switch (getNodeType()) { 99 case ARRAY: case OBJECT: case MISSING: 100 return false; 101 default: 102 return true; 103 } 104 } 105 106 @Override 107 public final boolean isContainerNode() { 108 final JsonNodeType type = getNodeType(); 109 return type == JsonNodeType.OBJECT || type == JsonNodeType.ARRAY; 110 } 111 112 @Override 113 public boolean isMissingNode() { 114 return false; 115 } 116 117 @Override 118 public boolean isArray() { 119 return false; 120 } 121 122 @Override 123 public boolean isObject() { 124 return false; 125 } 126 127 /** 128 * Method for accessing value of the specified element of 129 * an array node. For other nodes, null is always returned. 130 *<p> 131 * For array nodes, index specifies 132 * exact location within array and allows for efficient iteration 133 * over child elements (underlying storage is guaranteed to 134 * be efficiently indexable, i.e. has random-access to elements). 135 * If index is less than 0, or equal-or-greater than 136 * <code>node.size()</code>, null is returned; no exception is 137 * thrown for any index. 138 *<p> 139 * NOTE: if the element value has been explicitly set as <code>null</code> 140 * (which is different from removal!), 141 * a {@link edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind.node.NullNode} will be returned, 142 * not null. 143 * 144 * @return Node that represent value of the specified element, 145 * if this node is an array and has specified element. 146 * Null otherwise. 147 */ 148 @Override 149 public abstract JsonNode get(int index); 150 151 /** 152 * Method for accessing value of the specified field of 153 * an object node. If this node is not an object (or it 154 * does not have a value for specified field name), or 155 * if there is no field with such name, null is returned. 156 *<p> 157 * NOTE: if the property value has been explicitly set as <code>null</code> 158 * (which is different from removal!), 159 * a {@link edu.internet2.middleware.grouperClientExt.com.fasterxml.jackson.databind.node.NullNode} will be returned, 160 * not null. 161 * 162 * @return Node that represent value of the specified field, 163 * if this node is an object and has value for the specified 164 * field. Null otherwise. 165 */ 166 @Override 167 public JsonNode get(String fieldName) { return null; } 168 /** 169 * This method is similar to {@link #get(String)}, except 170 * that instead of returning null if no such value exists (due 171 * to this node not being an object, or object not having value 172 * for the specified field), 173 * a "missing node" (node that returns true for 174 * {@link #isMissingNode}) will be returned. This allows for 175 * convenient and safe chained access via path calls. 176 */ 177 178 @Override 179 public abstract JsonNode path(String fieldName); 180 181 /** 182 * This method is similar to {@link #get(int)}, except 183 * that instead of returning null if no such element exists (due 184 * to index being out of range, or this node not being an array), 185 * a "missing node" (node that returns true for 186 * {@link #isMissingNode}) will be returned. This allows for 187 * convenient and safe chained access via path calls. 188 */ 189 @Override 190 public abstract JsonNode path(int index); 191 192 @Override 193 public Iterator<String> fieldNames() { 194 return ClassUtil.emptyIterator(); 195 } 196 197 /** 198 * Method for locating node specified by given JSON pointer instances. 199 * Method will never return null; if no matching node exists, 200 * will return a node for which {@link #isMissingNode()} returns true. 201 * 202 * @return Node that matches given JSON Pointer: if no match exists, 203 * will return a node for which {@link #isMissingNode()} returns true. 204 * 205 * @since 2.3 206 */ 207 @Override 208 public final JsonNode at(JsonPointer ptr) 209 { 210 // Basically: value nodes only match if we have "empty" path left 211 if (ptr.matches()) { 212 return this; 213 } 214 JsonNode n = _at(ptr); 215 if (n == null) { 216 return MissingNode.getInstance(); 217 } 218 return n.at(ptr.tail()); 219 } 220 221 /** 222 * Convenience method that is functionally equivalent to: 223 *<pre> 224 * return at(JsonPointer.valueOf(jsonPointerExpression)); 225 *</pre> 226 *<p> 227 * Note that if the same expression is used often, it is preferable to construct 228 * {@link JsonPointer} instance once and reuse it: this method will not perform 229 * any caching of compiled expressions. 230 * 231 * @param jsonPtrExpr Expression to compile as a {@link JsonPointer} 232 * instance 233 * 234 * @return Node that matches given JSON Pointer: if no match exists, 235 * will return a node for which {@link TreeNode#isMissingNode()} returns true. 236 * 237 * @since 2.3 238 */ 239 @Override 240 public final JsonNode at(String jsonPtrExpr) { 241 return at(JsonPointer.compile(jsonPtrExpr)); 242 } 243 244 /** 245 * Helper method used by other methods for traversing the next step 246 * of given path expression, and returning matching value node if any: 247 * if no match, {@code null} is returned. 248 * 249 * @param ptr Path expression to use 250 * 251 * @return Either matching {@link JsonNode} for the first step of path or 252 * {@code null} if no match (including case that this node is not a container) 253 */ 254 protected abstract JsonNode _at(JsonPointer ptr); 255 256 /* 257 /********************************************************** 258 /* Public API, type introspection 259 /********************************************************** 260 */ 261 262 // // First high-level division between values, containers and "missing" 263 264 /** 265 * Return the type of this node 266 * 267 * @return the node type as a {@link JsonNodeType} enum value 268 * 269 * @since 2.2 270 */ 271 public abstract JsonNodeType getNodeType(); 272 273 /** 274 * Method that can be used to check if the node is a wrapper 275 * for a POJO ("Plain Old Java Object" aka "bean". 276 * Returns true only for 277 * instances of <code>POJONode</code>. 278 * 279 * @return True if this node wraps a POJO 280 */ 281 public final boolean isPojo() { 282 return getNodeType() == JsonNodeType.POJO; 283 } 284 285 /** 286 * @return True if this node represents a numeric JSON value 287 */ 288 public final boolean isNumber() { 289 return getNodeType() == JsonNodeType.NUMBER; 290 } 291 292 /** 293 * 294 * @return True if this node represents an integral (integer) 295 * numeric JSON value 296 */ 297 public boolean isIntegralNumber() { return false; } 298 299 /** 300 * @return True if this node represents a non-integral 301 * numeric JSON value 302 */ 303 public boolean isFloatingPointNumber() { return false; } 304 305 /** 306 * Method that can be used to check whether contained value 307 * is a number represented as Java <code>short</code>. 308 * Note, however, that even if this method returns false, it 309 * is possible that conversion would be possible from other numeric 310 * types -- to check if this is possible, use 311 * {@link #canConvertToInt()} instead. 312 * 313 * @return True if the value contained by this node is stored as Java short 314 */ 315 public boolean isShort() { return false; } 316 317 /** 318 * Method that can be used to check whether contained value 319 * is a number represented as Java <code>int</code>. 320 * Note, however, that even if this method returns false, it 321 * is possible that conversion would be possible from other numeric 322 * types -- to check if this is possible, use 323 * {@link #canConvertToInt()} instead. 324 * 325 * @return True if the value contained by this node is stored as Java int 326 */ 327 public boolean isInt() { return false; } 328 329 /** 330 * Method that can be used to check whether contained value 331 * is a number represented as Java <code>long</code>. 332 * Note, however, that even if this method returns false, it 333 * is possible that conversion would be possible from other numeric 334 * types -- to check if this is possible, use 335 * {@link #canConvertToLong()} instead. 336 * 337 * @return True if the value contained by this node is stored as Java <code>long</code> 338 */ 339 public boolean isLong() { return false; } 340 341 /** 342 * @since 2.2 343 */ 344 public boolean isFloat() { return false; } 345 346 public boolean isDouble() { return false; } 347 public boolean isBigDecimal() { return false; } 348 public boolean isBigInteger() { return false; } 349 350 /** 351 * Method that checks whether this node represents basic JSON String 352 * value. 353 */ 354 public final boolean isTextual() { 355 return getNodeType() == JsonNodeType.STRING; 356 } 357 358 /** 359 * Method that can be used to check if this node was created from 360 * JSON boolean value (literals "true" and "false"). 361 */ 362 public final boolean isBoolean() { 363 return getNodeType() == JsonNodeType.BOOLEAN; 364 } 365 366 /** 367 * Method that can be used to check if this node was created from 368 * JSON literal null value. 369 */ 370 public final boolean isNull() { 371 return getNodeType() == JsonNodeType.NULL; 372 } 373 374 /** 375 * Method that can be used to check if this node represents 376 * binary data (Base64 encoded). Although this will be externally 377 * written as JSON String value, {@link #isTextual} will 378 * return false if this method returns true. 379 * 380 * @return True if this node represents base64 encoded binary data 381 */ 382 public final boolean isBinary() { 383 return getNodeType() == JsonNodeType.BINARY; 384 } 385 386 /** 387 * Method that can be used to check whether this node is a numeric 388 * node ({@link #isNumber} would return true) AND its value fits 389 * within Java's 32-bit signed integer type, <code>int</code>. 390 * Note that floating-point numbers are convertible if the integral 391 * part fits without overflow (as per standard Java coercion rules) 392 *<p> 393 * NOTE: this method does not consider possible value type conversion 394 * from JSON String into Number; so even if this method returns false, 395 * it is possible that {@link #asInt} could still succeed 396 * if node is a JSON String representing integral number, or boolean. 397 * 398 * @since 2.0 399 */ 400 public boolean canConvertToInt() { return false; } 401 402 /** 403 * Method that can be used to check whether this node is a numeric 404 * node ({@link #isNumber} would return true) AND its value fits 405 * within Java's 64-bit signed integer type, <code>long</code>. 406 * Note that floating-point numbers are convertible if the integral 407 * part fits without overflow (as per standard Java coercion rules) 408 *<p> 409 * NOTE: this method does not consider possible value type conversion 410 * from JSON String into Number; so even if this method returns false, 411 * it is possible that {@link #asLong} could still succeed 412 * if node is a JSON String representing integral number, or boolean. 413 * 414 * @since 2.0 415 */ 416 public boolean canConvertToLong() { return false; } 417 418 /** 419 * Method that can be used to check whether contained value 420 * is numeric (returns true for {@link #isNumber()}) and 421 * can be losslessly converted to integral number (specifically, 422 * {@link BigInteger} but potentially others, see 423 * {@link #canConvertToInt} and {@link #canConvertToInt}). 424 * Latter part allows floating-point numbers 425 * (for which {@link #isFloatingPointNumber()} returns {@code true}) 426 * that do not have fractional part. 427 * Note that "not-a-number" values of {@code double} and {@code float} 428 * will return {@code false} as they can not be converted to matching 429 * integral representations. 430 * 431 * @return True if the value is an actual number with no fractional 432 * part; false for non-numeric types, NaN representations of floating-point 433 * numbers, and floating-point numbers with fractional part. 434 * 435 * @since 2.12 436 */ 437 public boolean canConvertToExactIntegral() { 438 return isIntegralNumber(); 439 } 440 441 /* 442 /********************************************************** 443 /* Public API, straight value access 444 /********************************************************** 445 */ 446 447 /** 448 * Method to use for accessing String values. 449 * Does <b>NOT</b> do any conversions for non-String value nodes; 450 * for non-String values (ones for which {@link #isTextual} returns 451 * false) null will be returned. 452 * For String values, null is never returned (but empty Strings may be) 453 * 454 * @return Textual value this node contains, iff it is a textual 455 * JSON node (comes from JSON String value entry) 456 */ 457 public String textValue() { return null; } 458 459 /** 460 * Method to use for accessing binary content of binary nodes (nodes 461 * for which {@link #isBinary} returns true); or for Text Nodes 462 * (ones for which {@link #textValue} returns non-null value), 463 * to read decoded base64 data. 464 * For other types of nodes, returns null. 465 * 466 * @return Binary data this node contains, iff it is a binary 467 * node; null otherwise 468 */ 469 public byte[] binaryValue() throws IOException { 470 return null; 471 } 472 473 /** 474 * Method to use for accessing JSON boolean values (value 475 * literals 'true' and 'false'). 476 * For other types, always returns false. 477 * 478 * @return Textual value this node contains, iff it is a textual 479 * json node (comes from JSON String value entry) 480 */ 481 public boolean booleanValue() { return false; } 482 483 /** 484 * Returns numeric value for this node, <b>if and only if</b> 485 * this node is numeric ({@link #isNumber} returns true); otherwise 486 * returns null 487 * 488 * @return Number value this node contains, if any (null for non-number 489 * nodes). 490 */ 491 public Number numberValue() { return null; } 492 493 /** 494 * Returns 16-bit short value for this node, <b>if and only if</b> 495 * this node is numeric ({@link #isNumber} returns true). For other 496 * types returns 0. 497 * For floating-point numbers, value is truncated using default 498 * Java coercion, similar to how cast from double to short operates. 499 * 500 * @return Short value this node contains, if any; 0 for non-number 501 * nodes. 502 */ 503 public short shortValue() { return 0; } 504 505 /** 506 * Returns integer value for this node, <b>if and only if</b> 507 * this node is numeric ({@link #isNumber} returns true). For other 508 * types returns 0. 509 * For floating-point numbers, value is truncated using default 510 * Java coercion, similar to how cast from double to int operates. 511 * 512 * @return Integer value this node contains, if any; 0 for non-number 513 * nodes. 514 */ 515 public int intValue() { return 0; } 516 517 /** 518 * Returns 64-bit long value for this node, <b>if and only if</b> 519 * this node is numeric ({@link #isNumber} returns true). For other 520 * types returns 0. 521 * For floating-point numbers, value is truncated using default 522 * Java coercion, similar to how cast from double to long operates. 523 * 524 * @return Long value this node contains, if any; 0 for non-number 525 * nodes. 526 */ 527 public long longValue() { return 0L; } 528 529 /** 530 * Returns 32-bit floating value for this node, <b>if and only if</b> 531 * this node is numeric ({@link #isNumber} returns true). For other 532 * types returns 0.0. 533 * For integer values, conversion is done using coercion; this means 534 * that an overflow is possible for `long` values 535 * 536 * @return 32-bit float value this node contains, if any; 0.0 for non-number nodes. 537 * 538 * @since 2.2 539 */ 540 public float floatValue() { return 0.0f; } 541 542 /** 543 * Returns 64-bit floating point (double) value for this node, <b>if and only if</b> 544 * this node is numeric ({@link #isNumber} returns true). For other 545 * types returns 0.0. 546 * For integer values, conversion is done using coercion; this may result 547 * in overflows with {@link BigInteger} values. 548 * 549 * @return 64-bit double value this node contains, if any; 0.0 for non-number nodes. 550 * 551 * @since 2.2 552 */ 553 public double doubleValue() { return 0.0; } 554 555 /** 556 * Returns floating point value for this node (as {@link BigDecimal}), <b>if and only if</b> 557 * this node is numeric ({@link #isNumber} returns true). For other 558 * types returns <code>BigDecimal.ZERO</code>. 559 * 560 * @return {@link BigDecimal} value this node contains, if numeric node; <code>BigDecimal.ZERO</code> for non-number nodes. 561 */ 562 public BigDecimal decimalValue() { return BigDecimal.ZERO; } 563 564 /** 565 * Returns integer value for this node (as {@link BigDecimal}), <b>if and only if</b> 566 * this node is numeric ({@link #isNumber} returns true). For other 567 * types returns <code>BigInteger.ZERO</code>. 568 * 569 * @return {@link BigInteger} value this node contains, if numeric node; <code>BigInteger.ZERO</code> for non-number nodes. 570 */ 571 public BigInteger bigIntegerValue() { return BigInteger.ZERO; } 572 573 /* 574 /********************************************************** 575 /* Public API, value access with conversion(s)/coercion(s) 576 /********************************************************** 577 */ 578 579 /** 580 * Method that will return a valid String representation of 581 * the container value, if the node is a value node 582 * (method {@link #isValueNode} returns true), 583 * otherwise empty String. 584 */ 585 public abstract String asText(); 586 587 /** 588 * Method similar to {@link #asText()}, except that it will return 589 * <code>defaultValue</code> in cases where null value would be returned; 590 * either for missing nodes (trying to access missing property, or element 591 * at invalid item for array) or explicit nulls. 592 * 593 * @since 2.4 594 */ 595 public String asText(String defaultValue) { 596 String str = asText(); 597 return (str == null) ? defaultValue : str; 598 } 599 600 /** 601 * Method that will try to convert value of this node to a Java <b>int</b>. 602 * Numbers are coerced using default Java rules; booleans convert to 0 (false) 603 * and 1 (true), and Strings are parsed using default Java language integer 604 * parsing rules. 605 *<p> 606 * If representation cannot be converted to an int (including structured types 607 * like Objects and Arrays), 608 * default value of <b>0</b> will be returned; no exceptions are thrown. 609 */ 610 public int asInt() { 611 return asInt(0); 612 } 613 614 /** 615 * Method that will try to convert value of this node to a Java <b>int</b>. 616 * Numbers are coerced using default Java rules; booleans convert to 0 (false) 617 * and 1 (true), and Strings are parsed using default Java language integer 618 * parsing rules. 619 *<p> 620 * If representation cannot be converted to an int (including structured types 621 * like Objects and Arrays), 622 * specified <b>defaultValue</b> will be returned; no exceptions are thrown. 623 */ 624 public int asInt(int defaultValue) { 625 return defaultValue; 626 } 627 628 /** 629 * Method that will try to convert value of this node to a Java <b>long</b>. 630 * Numbers are coerced using default Java rules; booleans convert to 0 (false) 631 * and 1 (true), and Strings are parsed using default Java language integer 632 * parsing rules. 633 *<p> 634 * If representation cannot be converted to a long (including structured types 635 * like Objects and Arrays), 636 * default value of <b>0</b> will be returned; no exceptions are thrown. 637 */ 638 public long asLong() { 639 return asLong(0L); 640 } 641 642 /** 643 * Method that will try to convert value of this node to a Java <b>long</b>. 644 * Numbers are coerced using default Java rules; booleans convert to 0 (false) 645 * and 1 (true), and Strings are parsed using default Java language integer 646 * parsing rules. 647 *<p> 648 * If representation cannot be converted to a long (including structured types 649 * like Objects and Arrays), 650 * specified <b>defaultValue</b> will be returned; no exceptions are thrown. 651 */ 652 public long asLong(long defaultValue) { 653 return defaultValue; 654 } 655 656 /** 657 * Method that will try to convert value of this node to a Java <b>double</b>. 658 * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) 659 * and 1.0 (true), and Strings are parsed using default Java language integer 660 * parsing rules. 661 *<p> 662 * If representation cannot be converted to an int (including structured types 663 * like Objects and Arrays), 664 * default value of <b>0.0</b> will be returned; no exceptions are thrown. 665 */ 666 public double asDouble() { 667 return asDouble(0.0); 668 } 669 670 /** 671 * Method that will try to convert value of this node to a Java <b>double</b>. 672 * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) 673 * and 1.0 (true), and Strings are parsed using default Java language integer 674 * parsing rules. 675 *<p> 676 * If representation cannot be converted to an int (including structured types 677 * like Objects and Arrays), 678 * specified <b>defaultValue</b> will be returned; no exceptions are thrown. 679 */ 680 public double asDouble(double defaultValue) { 681 return defaultValue; 682 } 683 684 /** 685 * Method that will try to convert value of this node to a Java <b>boolean</b>. 686 * JSON booleans map naturally; integer numbers other than 0 map to true, and 687 * 0 maps to false 688 * and Strings 'true' and 'false' map to corresponding values. 689 *<p> 690 * If representation cannot be converted to a boolean value (including structured types 691 * like Objects and Arrays), 692 * default value of <b>false</b> will be returned; no exceptions are thrown. 693 */ 694 public boolean asBoolean() { 695 return asBoolean(false); 696 } 697 698 /** 699 * Method that will try to convert value of this node to a Java <b>boolean</b>. 700 * JSON booleans map naturally; integer numbers other than 0 map to true, and 701 * 0 maps to false 702 * and Strings 'true' and 'false' map to corresponding values. 703 *<p> 704 * If representation cannot be converted to a boolean value (including structured types 705 * like Objects and Arrays), 706 * specified <b>defaultValue</b> will be returned; no exceptions are thrown. 707 */ 708 public boolean asBoolean(boolean defaultValue) { 709 return defaultValue; 710 } 711 712 /* 713 /********************************************************************** 714 /* Public API, extended traversal (2.10) with "required()" 715 /********************************************************************** 716 */ 717 718 /** 719 * Method that may be called to verify that {@code this} node is NOT so-called 720 * "missing node": that is, one for which {@link #isMissingNode()} returns {@code true}. 721 * If not missing node, {@code this} is returned to allow chaining; otherwise 722 * {@link IllegalArgumentException} is thrown. 723 * 724 * @return {@code this} node to allow chaining 725 * 726 * @throws IllegalArgumentException if this node is "missing node" 727 * 728 * @since 2.10 729 */ 730 public <T extends JsonNode> T require() throws IllegalArgumentException { 731 return _this(); 732 } 733 734 /** 735 * Method that may be called to verify that {@code this} node is neither so-called 736 * "missing node" (that is, one for which {@link #isMissingNode()} returns {@code true}) 737 * nor "null node" (one for which {@link #isNull()} returns {@code true}). 738 * If non-null non-missing node, {@code this} is returned to allow chaining; otherwise 739 * {@link IllegalArgumentException} is thrown. 740 * 741 * @return {@code this} node to allow chaining 742 * 743 * @throws IllegalArgumentException if this node is either "missing node" or "null node" 744 * 745 * @since 2.10 746 */ 747 public <T extends JsonNode> T requireNonNull() throws IllegalArgumentException { 748 return _this(); 749 } 750 751 /** 752 * Method is functionally equivalent to 753 *{@code 754 * path(fieldName).required() 755 *} 756 * and can be used to check that this node is an {@code ObjectNode} (that is, represents 757 * JSON Object value) and has value for specified property with key {@code fieldName} 758 * (but note that value may be explicit JSON null value). 759 * If this node is Object Node and has value for specified property, matching value 760 * is returned; otherwise {@link IllegalArgumentException} is thrown. 761 * 762 * @param propertyName Name of property to access 763 * 764 * @return Value of the specified property of this Object node 765 * 766 * @throws IllegalArgumentException if this node is not an Object node or if it does not 767 * have value for specified property 768 * 769 * @since 2.10 770 */ 771 public JsonNode required(String propertyName) throws IllegalArgumentException { 772 return _reportRequiredViolation("Node of type `%s` has no fields", getClass().getName()); 773 } 774 775 /** 776 * Method is functionally equivalent to 777 *{@code 778 * path(index).required() 779 *} 780 * and can be used to check that this node is an {@code ArrayNode} (that is, represents 781 * JSON Array value) and has value for specified {@code index} 782 * (but note that value may be explicit JSON null value). 783 * If this node is Array Node and has value for specified index, value at index 784 * is returned; otherwise {@link IllegalArgumentException} is thrown. 785 * 786 * @param index Index of the value of this Array node to access 787 * 788 * @return Value at specified index of this Array node 789 * 790 * @throws IllegalArgumentException if this node is not an Array node or if it does not 791 * have value for specified index 792 * 793 * @since 2.10 794 */ 795 public JsonNode required(int index) throws IllegalArgumentException { 796 return _reportRequiredViolation("Node of type `%s` has no indexed values", getClass().getName()); 797 } 798 799 /** 800 * Method is functionally equivalent to 801 *{@code 802 * at(pathExpr).required() 803 *} 804 * and can be used to check that there is an actual value node at specified {@link JsonPointer} 805 * starting from {@code this} node 806 * (but note that value may be explicit JSON null value). 807 * If such value node exists it is returned; 808 * otherwise {@link IllegalArgumentException} is thrown. 809 * 810 * @param pathExpr {@link JsonPointer} expression (as String) to use for finding value node 811 * 812 * @return Matching value node for given expression 813 * 814 * @throws IllegalArgumentException if no value node exists at given {@code JSON Pointer} path 815 * 816 * @since 2.10 817 */ 818 public JsonNode requiredAt(String pathExpr) throws IllegalArgumentException { 819 return requiredAt(JsonPointer.compile(pathExpr)); 820 } 821 822 /** 823 * Method is functionally equivalent to 824 *{@code 825 * at(path).required() 826 *} 827 * and can be used to check that there is an actual value node at specified {@link JsonPointer} 828 * starting from {@code this} node 829 * (but note that value may be explicit JSON null value). 830 * If such value node exists it is returned; 831 * otherwise {@link IllegalArgumentException} is thrown. 832 * 833 * @param path {@link JsonPointer} expression to use for finding value node 834 * 835 * @return Matching value node for given expression 836 * 837 * @throws IllegalArgumentException if no value node exists at given {@code JSON Pointer} path 838 * 839 * @since 2.10 840 */ 841 public final JsonNode requiredAt(final JsonPointer path) throws IllegalArgumentException { 842 JsonPointer currentExpr = path; 843 JsonNode curr = this; 844 845 // Note: copied from `at()` 846 while (true) { 847 if (currentExpr.matches()) { 848 return curr; 849 } 850 curr = curr._at(currentExpr); // lgtm [java/dereferenced-value-may-be-null] 851 if (curr == null) { 852 _reportRequiredViolation("No node at '%s' (unmatched part: '%s')", 853 path, currentExpr); 854 } 855 currentExpr = currentExpr.tail(); 856 } 857 } 858 859 /* 860 /********************************************************** 861 /* Public API, value find / existence check methods 862 /********************************************************** 863 */ 864 865 /** 866 * Method that allows checking whether this node is JSON Object node 867 * and contains value for specified property. If this is the case 868 * (including properties with explicit null values), returns true; 869 * otherwise returns false. 870 *<p> 871 * This method is equivalent to: 872 *<pre> 873 * node.get(fieldName) != null 874 *</pre> 875 * (since return value of get() is node, not value node contains) 876 *<p> 877 * NOTE: when explicit <code>null</code> values are added, this 878 * method will return <code>true</code> for such properties. 879 * 880 * @param fieldName Name of element to check 881 * 882 * @return True if this node is a JSON Object node, and has a property 883 * entry with specified name (with any value, including null value) 884 */ 885 public boolean has(String fieldName) { 886 return get(fieldName) != null; 887 } 888 889 /** 890 * Method that allows checking whether this node is JSON Array node 891 * and contains a value for specified index 892 * If this is the case 893 * (including case of specified indexing having null as value), returns true; 894 * otherwise returns false. 895 *<p> 896 * Note: array element indexes are 0-based. 897 *<p> 898 * This method is equivalent to: 899 *<pre> 900 * node.get(index) != null 901 *</pre> 902 *<p> 903 * NOTE: this method will return <code>true</code> for explicitly added 904 * null values. 905 * 906 * @param index Index to check 907 * 908 * @return True if this node is a JSON Object node, and has a property 909 * entry with specified name (with any value, including null value) 910 */ 911 public boolean has(int index) { 912 return get(index) != null; 913 } 914 915 /** 916 * Method that is similar to {@link #has(String)}, but that will 917 * return <code>false</code> for explicitly added nulls. 918 *<p> 919 * This method is functionally equivalent to: 920 *<pre> 921 * node.get(fieldName) != null && !node.get(fieldName).isNull() 922 *</pre> 923 * 924 * @since 2.1 925 */ 926 public boolean hasNonNull(String fieldName) { 927 JsonNode n = get(fieldName); 928 return (n != null) && !n.isNull(); 929 } 930 931 /** 932 * Method that is similar to {@link #has(int)}, but that will 933 * return <code>false</code> for explicitly added nulls. 934 *<p> 935 * This method is equivalent to: 936 *<pre> 937 * node.get(index) != null && !node.get(index).isNull() 938 *</pre> 939 * 940 * @since 2.1 941 */ 942 public boolean hasNonNull(int index) { 943 JsonNode n = get(index); 944 return (n != null) && !n.isNull(); 945 } 946 947 /* 948 /********************************************************** 949 /* Public API, container access 950 /********************************************************** 951 */ 952 953 /** 954 * Same as calling {@link #elements}; implemented so that 955 * convenience "for-each" loop can be used for looping over elements 956 * of JSON Array constructs. 957 */ 958 @Override 959 public final Iterator<JsonNode> iterator() { return elements(); } 960 961 /** 962 * Method for accessing all value nodes of this Node, iff 963 * this node is a JSON Array or Object node. In case of Object node, 964 * field names (keys) are not included, only values. 965 * For other types of nodes, returns empty iterator. 966 */ 967 public Iterator<JsonNode> elements() { 968 return ClassUtil.emptyIterator(); 969 } 970 971 /** 972 * @return Iterator that can be used to traverse all key/value pairs for 973 * object nodes; empty iterator (no contents) for other types 974 */ 975 public Iterator<Map.Entry<String, JsonNode>> fields() { 976 return ClassUtil.emptyIterator(); 977 } 978 979 /* 980 /********************************************************** 981 /* Public API, find methods 982 /********************************************************** 983 */ 984 985 /** 986 * Method for finding a JSON Object field with specified name in this 987 * node or its child nodes, and returning value it has. 988 * If no matching field is found in this node or its descendants, returns null. 989 * 990 * @param fieldName Name of field to look for 991 * 992 * @return Value of first matching node found, if any; null if none 993 */ 994 public abstract JsonNode findValue(String fieldName); 995 996 /** 997 * Method for finding JSON Object fields with specified name, and returning 998 * found ones as a List. Note that sub-tree search ends if a field is found, 999 * so possible children of result nodes are <b>not</b> included. 1000 * If no matching fields are found in this node or its descendants, returns 1001 * an empty List. 1002 * 1003 * @param fieldName Name of field to look for 1004 */ 1005 public final List<JsonNode> findValues(String fieldName) 1006 { 1007 List<JsonNode> result = findValues(fieldName, null); 1008 if (result == null) { 1009 return Collections.emptyList(); 1010 } 1011 return result; 1012 } 1013 1014 /** 1015 * Similar to {@link #findValues}, but will additionally convert 1016 * values into Strings, calling {@link #asText}. 1017 */ 1018 public final List<String> findValuesAsText(String fieldName) 1019 { 1020 List<String> result = findValuesAsText(fieldName, null); 1021 if (result == null) { 1022 return Collections.emptyList(); 1023 } 1024 return result; 1025 } 1026 1027 /** 1028 * Method similar to {@link #findValue}, but that will return a 1029 * "missing node" instead of null if no field is found. Missing node 1030 * is a specific kind of node for which {@link #isMissingNode} 1031 * returns true; and all value access methods return empty or 1032 * missing value. 1033 * 1034 * @param fieldName Name of field to look for 1035 * 1036 * @return Value of first matching node found; or if not found, a 1037 * "missing node" (non-null instance that has no value) 1038 */ 1039 public abstract JsonNode findPath(String fieldName); 1040 1041 /** 1042 * Method for finding a JSON Object that contains specified field, 1043 * within this node or its descendants. 1044 * If no matching field is found in this node or its descendants, returns null. 1045 * 1046 * @param fieldName Name of field to look for 1047 * 1048 * @return Value of first matching node found, if any; null if none 1049 */ 1050 public abstract JsonNode findParent(String fieldName); 1051 1052 /** 1053 * Method for finding a JSON Object that contains specified field, 1054 * within this node or its descendants. 1055 * If no matching field is found in this node or its descendants, returns null. 1056 * 1057 * @param fieldName Name of field to look for 1058 * 1059 * @return Value of first matching node found, if any; null if none 1060 */ 1061 public final List<JsonNode> findParents(String fieldName) 1062 { 1063 List<JsonNode> result = findParents(fieldName, null); 1064 if (result == null) { 1065 return Collections.emptyList(); 1066 } 1067 return result; 1068 } 1069 1070 public abstract List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar); 1071 public abstract List<String> findValuesAsText(String fieldName, List<String> foundSoFar); 1072 public abstract List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar); 1073 1074 /* 1075 /********************************************************** 1076 /* Public API, path handling 1077 /********************************************************** 1078 */ 1079 1080 /** 1081 * Method that can be called on Object nodes, to access a property 1082 * that has Object value; or if no such property exists, to create, 1083 * add and return such Object node. 1084 * If the node method is called on is not Object node, 1085 * or if property exists and has value that is not Object node, 1086 * {@link UnsupportedOperationException} is thrown 1087 *<p> 1088 * NOTE: since 2.10 has had co-variant return type 1089 */ 1090 public <T extends JsonNode> T with(String propertyName) { 1091 throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " 1092 +getClass().getName()+"), cannot call with() on it"); 1093 } 1094 1095 /** 1096 * Method that can be called on Object nodes, to access a property 1097 * that has <code>Array</code> value; or if no such property exists, to create, 1098 * add and return such Array node. 1099 * If the node method is called on is not Object node, 1100 * or if property exists and has value that is not Array node, 1101 * {@link UnsupportedOperationException} is thrown 1102 *<p> 1103 * NOTE: since 2.10 has had co-variant return type 1104 */ 1105 public <T extends JsonNode> T withArray(String propertyName) { 1106 throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " 1107 +getClass().getName()+"), cannot call withArray() on it"); 1108 } 1109 1110 /* 1111 /********************************************************** 1112 /* Public API, comparison 1113 /********************************************************** 1114 */ 1115 1116 /** 1117 * Entry method for invoking customizable comparison, using passed-in 1118 * {@link Comparator} object. Nodes will handle traversal of structured 1119 * types (arrays, objects), but defer to comparator for scalar value 1120 * comparisons. If a "natural" {@link Comparator} is passed -- one that 1121 * simply calls <code>equals()</code> on one of arguments, passing the other 1122 * -- implementation is the same as directly calling <code>equals()</code> 1123 * on node. 1124 *<p> 1125 * Default implementation simply delegates to passed in <code>comparator</code>, 1126 * with <code>this</code> as the first argument, and <code>other</code> as 1127 * the second argument. 1128 * 1129 * @param comparator Object called to compare two scalar {@link JsonNode} 1130 * instances, and return either 0 (are equals) or non-zero (not equal) 1131 * 1132 * @since 2.6 1133 */ 1134 public boolean equals(Comparator<JsonNode> comparator, JsonNode other) { 1135 return comparator.compare(this, other) == 0; 1136 } 1137 1138 /* 1139 /********************************************************** 1140 /* Overridden standard methods 1141 /********************************************************** 1142 */ 1143 1144 /** 1145 * Method that will produce (as of Jackson 2.10) valid JSON using 1146 * default settings of databind, as String. 1147 * If you want other kinds of JSON output (or output formatted using one of 1148 * other Jackson-supported data formats) make sure to use 1149 * {@link ObjectMapper} or {@link ObjectWriter} to serialize an 1150 * instance, for example: 1151 *<pre> 1152 * String json = objectMapper.writeValueAsString(rootNode); 1153 *</pre> 1154 *<p> 1155 * Note: method defined as abstract to ensure all implementation 1156 * classes explicitly implement method, instead of relying 1157 * on {@link Object#toString()} definition. 1158 */ 1159 @Override 1160 public abstract String toString(); 1161 1162 /** 1163 * Alternative to {@link #toString} that will serialize this node using 1164 * Jackson default pretty-printer. 1165 * 1166 * @since 2.10 1167 */ 1168 public String toPrettyString() { 1169 return toString(); 1170 } 1171 1172 /** 1173 * Equality for node objects is defined as full (deep) value 1174 * equality. This means that it is possible to compare complete 1175 * JSON trees for equality by comparing equality of root nodes. 1176 *<p> 1177 * Note: marked as abstract to ensure all implementation 1178 * classes define it properly and not rely on definition 1179 * from {@link java.lang.Object}. 1180 */ 1181 @Override 1182 public abstract boolean equals(Object o); 1183 1184 /* 1185 /********************************************************************** 1186 /* Helper methods, for sub-classes 1187 /********************************************************************** 1188 */ 1189 1190 // @since 2.10 1191 @SuppressWarnings("unchecked") 1192 protected <T extends JsonNode> T _this() { 1193 return (T) this; 1194 } 1195 1196 /** 1197 * Helper method that throws {@link IllegalArgumentException} as a result of 1198 * violating "required-constraint" for this node (for {@link #required} or related 1199 * methods). 1200 */ 1201 protected <T> T _reportRequiredViolation(String msgTemplate, Object...args) { 1202 throw new IllegalArgumentException(String.format(msgTemplate, args)); 1203 } 1204 }