| package com.fasterxml.jackson.databind; |
| |
| import java.io.IOException; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.*; |
| |
| import com.fasterxml.jackson.core.*; |
| import com.fasterxml.jackson.databind.node.JsonNodeType; |
| import com.fasterxml.jackson.databind.node.MissingNode; |
| import com.fasterxml.jackson.databind.util.ClassUtil; |
| |
| /** |
| * Base class for all JSON nodes, which form the basis of JSON |
| * Tree Model that Jackson implements. |
| * One way to think of these nodes is to consider them |
| * similar to DOM nodes in XML DOM trees. |
| *<p> |
| * As a general design rule, most accessors ("getters") are included |
| * in this base class, to allow for traversing structure without |
| * type casts. Most mutators, however, need to be accessed through |
| * specific sub-classes (such as <code>ObjectNode</code> |
| * and <code>ArrayNode</code>). |
| * This seems sensible because proper type |
| * information is generally available when building or modifying |
| * trees, but less often when reading a tree (newly built from |
| * parsed JSON content). |
| *<p> |
| * Actual concrete sub-classes can be found from package |
| * {@link com.fasterxml.jackson.databind.node}. |
| *<p> |
| * Note that it is possible to "read" from nodes, using |
| * method {@link TreeNode#traverse(ObjectCodec)}, which will result in |
| * a {@link JsonParser} being constructed. This can be used for (relatively) |
| * efficient conversations between different representations; and it is what |
| * core databind uses for methods like {@link ObjectMapper#treeToValue(TreeNode, Class)} |
| * and {@link ObjectMapper#treeAsTokens(TreeNode)} |
| */ |
| public abstract class JsonNode |
| extends JsonSerializable.Base // i.e. implements JsonSerializable |
| implements TreeNode, Iterable<JsonNode> |
| { |
| /* |
| /********************************************************** |
| /* Construction, related |
| /********************************************************** |
| */ |
| |
| protected JsonNode() { } |
| |
| /** |
| * Method that can be called to get a node that is guaranteed |
| * not to allow changing of this node through mutators on |
| * this node or any of its children. |
| * This means it can either make a copy of this node (and all |
| * mutable children and grand children nodes), or node itself |
| * if it is immutable. |
| *<p> |
| * Note: return type is guaranteed to have same type as the |
| * node method is called on; which is why method is declared |
| * with local generic type. |
| * |
| * @since 2.0 |
| * |
| * @return Node that is either a copy of this node (and all non-leaf |
| * children); or, for immutable leaf nodes, node itself. |
| */ |
| public abstract <T extends JsonNode> T deepCopy(); |
| |
| /* |
| /********************************************************** |
| /* TreeNode implementation |
| /********************************************************** |
| */ |
| |
| // public abstract JsonToken asToken(); |
| // public abstract JsonToken traverse(); |
| // public abstract JsonToken traverse(ObjectCodec codec); |
| // public abstract JsonParser.NumberType numberType(); |
| |
| @Override |
| public int size() { return 0; } |
| |
| @Override |
| public final boolean isValueNode() |
| { |
| switch (getNodeType()) { |
| case ARRAY: case OBJECT: case MISSING: |
| return false; |
| default: |
| return true; |
| } |
| } |
| |
| @Override |
| public final boolean isContainerNode() { |
| final JsonNodeType type = getNodeType(); |
| return type == JsonNodeType.OBJECT || type == JsonNodeType.ARRAY; |
| } |
| |
| @Override |
| public final boolean isMissingNode() { |
| return getNodeType() == JsonNodeType.MISSING; |
| } |
| |
| @Override |
| public final boolean isArray() { |
| return getNodeType() == JsonNodeType.ARRAY; |
| } |
| |
| @Override |
| public final boolean isObject() { |
| return getNodeType() == JsonNodeType.OBJECT; |
| } |
| |
| /** |
| * Method for accessing value of the specified element of |
| * an array node. For other nodes, null is always returned. |
| *<p> |
| * For array nodes, index specifies |
| * exact location within array and allows for efficient iteration |
| * over child elements (underlying storage is guaranteed to |
| * be efficiently indexable, i.e. has random-access to elements). |
| * If index is less than 0, or equal-or-greater than |
| * <code>node.size()</code>, null is returned; no exception is |
| * thrown for any index. |
| *<p> |
| * NOTE: if the element value has been explicitly set as <code>null</code> |
| * (which is different from removal!), |
| * a {@link com.fasterxml.jackson.databind.node.NullNode} will be returned, |
| * not null. |
| * |
| * @return Node that represent value of the specified element, |
| * if this node is an array and has specified element. |
| * Null otherwise. |
| */ |
| @Override |
| public abstract JsonNode get(int index); |
| |
| /** |
| * Method for accessing value of the specified field of |
| * an object node. If this node is not an object (or it |
| * does not have a value for specified field name), or |
| * if there is no field with such name, null is returned. |
| *<p> |
| * NOTE: if the property value has been explicitly set as <code>null</code> |
| * (which is different from removal!), |
| * a {@link com.fasterxml.jackson.databind.node.NullNode} will be returned, |
| * not null. |
| * |
| * @return Node that represent value of the specified field, |
| * if this node is an object and has value for the specified |
| * field. Null otherwise. |
| */ |
| @Override |
| public JsonNode get(String fieldName) { return null; } |
| /** |
| * This method is similar to {@link #get(String)}, except |
| * that instead of returning null if no such value exists (due |
| * to this node not being an object, or object not having value |
| * for the specified field), |
| * a "missing node" (node that returns true for |
| * {@link #isMissingNode}) will be returned. This allows for |
| * convenient and safe chained access via path calls. |
| */ |
| |
| @Override |
| public abstract JsonNode path(String fieldName); |
| |
| /** |
| * This method is similar to {@link #get(int)}, except |
| * that instead of returning null if no such element exists (due |
| * to index being out of range, or this node not being an array), |
| * a "missing node" (node that returns true for |
| * {@link #isMissingNode}) will be returned. This allows for |
| * convenient and safe chained access via path calls. |
| */ |
| @Override |
| public abstract JsonNode path(int index); |
| |
| @Override |
| public Iterator<String> fieldNames() { |
| return ClassUtil.emptyIterator(); |
| } |
| |
| /** |
| * Method for locating node specified by given JSON pointer instances. |
| * Method will never return null; if no matching node exists, |
| * will return a node for which {@link #isMissingNode()} returns true. |
| * |
| * @return Node that matches given JSON Pointer: if no match exists, |
| * will return a node for which {@link #isMissingNode()} returns true. |
| * |
| * @since 2.3 |
| */ |
| @Override |
| public final JsonNode at(JsonPointer ptr) |
| { |
| // Basically: value nodes only match if we have "empty" path left |
| if (ptr.matches()) { |
| return this; |
| } |
| JsonNode n = _at(ptr); |
| if (n == null) { |
| return MissingNode.getInstance(); |
| } |
| return n.at(ptr.tail()); |
| } |
| |
| /** |
| * Convenience method that is functionally equivalent to: |
| *<pre> |
| * return at(JsonPointer.valueOf(jsonPointerExpression)); |
| *</pre> |
| *<p> |
| * Note that if the same expression is used often, it is preferable to construct |
| * {@link JsonPointer} instance once and reuse it: this method will not perform |
| * any caching of compiled expressions. |
| * |
| * @param jsonPtrExpr Expression to compile as a {@link JsonPointer} |
| * instance |
| * |
| * @return Node that matches given JSON Pointer: if no match exists, |
| * will return a node for which {@link TreeNode#isMissingNode()} returns true. |
| * |
| * @since 2.3 |
| */ |
| @Override |
| public final JsonNode at(String jsonPtrExpr) { |
| return at(JsonPointer.compile(jsonPtrExpr)); |
| } |
| |
| protected abstract JsonNode _at(JsonPointer ptr); |
| |
| /* |
| /********************************************************** |
| /* Public API, type introspection |
| /********************************************************** |
| */ |
| |
| // // First high-level division between values, containers and "missing" |
| |
| /** |
| * Return the type of this node |
| * |
| * @return the node type as a {@link JsonNodeType} enum value |
| * |
| * @since 2.2 |
| */ |
| public abstract JsonNodeType getNodeType(); |
| |
| /** |
| * Method that can be used to check if the node is a wrapper |
| * for a POJO ("Plain Old Java Object" aka "bean". |
| * Returns true only for |
| * instances of <code>POJONode</code>. |
| * |
| * @return True if this node wraps a POJO |
| */ |
| public final boolean isPojo() { |
| return getNodeType() == JsonNodeType.POJO; |
| } |
| |
| /** |
| * @return True if this node represents a numeric JSON value |
| */ |
| public final boolean isNumber() { |
| return getNodeType() == JsonNodeType.NUMBER; |
| } |
| |
| /** |
| * |
| * @return True if this node represents an integral (integer) |
| * numeric JSON value |
| */ |
| public boolean isIntegralNumber() { return false; } |
| |
| /** |
| * @return True if this node represents a non-integral |
| * numeric JSON value |
| */ |
| public boolean isFloatingPointNumber() { return false; } |
| |
| /** |
| * Method that can be used to check whether contained value |
| * is a number represented as Java <code>short</code>. |
| * Note, however, that even if this method returns false, it |
| * is possible that conversion would be possible from other numeric |
| * types -- to check if this is possible, use |
| * {@link #canConvertToInt()} instead. |
| * |
| * @return True if the value contained by this node is stored as Java short |
| */ |
| public boolean isShort() { return false; } |
| |
| /** |
| * Method that can be used to check whether contained value |
| * is a number represented as Java <code>int</code>. |
| * Note, however, that even if this method returns false, it |
| * is possible that conversion would be possible from other numeric |
| * types -- to check if this is possible, use |
| * {@link #canConvertToInt()} instead. |
| * |
| * @return True if the value contained by this node is stored as Java int |
| */ |
| public boolean isInt() { return false; } |
| |
| /** |
| * Method that can be used to check whether contained value |
| * is a number represented as Java <code>long</code>. |
| * Note, however, that even if this method returns false, it |
| * is possible that conversion would be possible from other numeric |
| * types -- to check if this is possible, use |
| * {@link #canConvertToInt()} instead. |
| * |
| * @return True if the value contained by this node is stored as Java <code>long</code> |
| */ |
| public boolean isLong() { return false; } |
| |
| /** |
| * @since 2.2 |
| */ |
| public boolean isFloat() { return false; } |
| |
| public boolean isDouble() { return false; } |
| public boolean isBigDecimal() { return false; } |
| public boolean isBigInteger() { return false; } |
| |
| /** |
| * Method that checks whether this node represents basic JSON String |
| * value. |
| */ |
| public final boolean isTextual() { |
| return getNodeType() == JsonNodeType.STRING; |
| } |
| |
| /** |
| * Method that can be used to check if this node was created from |
| * JSON boolean value (literals "true" and "false"). |
| */ |
| public final boolean isBoolean() { |
| return getNodeType() == JsonNodeType.BOOLEAN; |
| } |
| |
| /** |
| * Method that can be used to check if this node was created from |
| * JSON literal null value. |
| */ |
| public final boolean isNull() { |
| return getNodeType() == JsonNodeType.NULL; |
| } |
| |
| /** |
| * Method that can be used to check if this node represents |
| * binary data (Base64 encoded). Although this will be externally |
| * written as JSON String value, {@link #isTextual} will |
| * return false if this method returns true. |
| * |
| * @return True if this node represents base64 encoded binary data |
| */ |
| public final boolean isBinary() { |
| return getNodeType() == JsonNodeType.BINARY; |
| } |
| |
| /** |
| * Method that can be used to check whether this node is a numeric |
| * node ({@link #isNumber} would return true) AND its value fits |
| * within Java's 32-bit signed integer type, <code>int</code>. |
| * Note that floating-point numbers are convertible if the integral |
| * part fits without overflow (as per standard Java coercion rules) |
| *<p> |
| * NOTE: this method does not consider possible value type conversion |
| * from JSON String into Number; so even if this method returns false, |
| * it is possible that {@link #asInt} could still succeed |
| * if node is a JSON String representing integral number, or boolean. |
| * |
| * @since 2.0 |
| */ |
| public boolean canConvertToInt() { return false; } |
| |
| /** |
| * Method that can be used to check whether this node is a numeric |
| * node ({@link #isNumber} would return true) AND its value fits |
| * within Java's 64-bit signed integer type, <code>long</code>. |
| * Note that floating-point numbers are convertible if the integral |
| * part fits without overflow (as per standard Java coercion rules) |
| *<p> |
| * NOTE: this method does not consider possible value type conversion |
| * from JSON String into Number; so even if this method returns false, |
| * it is possible that {@link #asLong} could still succeed |
| * if node is a JSON String representing integral number, or boolean. |
| * |
| * @since 2.0 |
| */ |
| public boolean canConvertToLong() { return false; } |
| |
| /* |
| /********************************************************** |
| /* Public API, straight value access |
| /********************************************************** |
| */ |
| |
| /** |
| * Method to use for accessing String values. |
| * Does <b>NOT</b> do any conversions for non-String value nodes; |
| * for non-String values (ones for which {@link #isTextual} returns |
| * false) null will be returned. |
| * For String values, null is never returned (but empty Strings may be) |
| * |
| * @return Textual value this node contains, iff it is a textual |
| * JSON node (comes from JSON String value entry) |
| */ |
| public String textValue() { return null; } |
| |
| /** |
| * Method to use for accessing binary content of binary nodes (nodes |
| * for which {@link #isBinary} returns true); or for Text Nodes |
| * (ones for which {@link #textValue} returns non-null value), |
| * to read decoded base64 data. |
| * For other types of nodes, returns null. |
| * |
| * @return Binary data this node contains, iff it is a binary |
| * node; null otherwise |
| */ |
| public byte[] binaryValue() throws IOException { |
| return null; |
| } |
| |
| /** |
| * Method to use for accessing JSON boolean values (value |
| * literals 'true' and 'false'). |
| * For other types, always returns false. |
| * |
| * @return Textual value this node contains, iff it is a textual |
| * json node (comes from JSON String value entry) |
| */ |
| public boolean booleanValue() { return false; } |
| |
| /** |
| * Returns numeric value for this node, <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true); otherwise |
| * returns null |
| * |
| * @return Number value this node contains, if any (null for non-number |
| * nodes). |
| */ |
| public Number numberValue() { return null; } |
| |
| /** |
| * Returns 16-bit short value for this node, <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns 0. |
| * For floating-point numbers, value is truncated using default |
| * Java coercion, similar to how cast from double to short operates. |
| * |
| * @return Short value this node contains, if any; 0 for non-number |
| * nodes. |
| */ |
| public short shortValue() { return 0; } |
| |
| /** |
| * Returns integer value for this node, <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns 0. |
| * For floating-point numbers, value is truncated using default |
| * Java coercion, similar to how cast from double to int operates. |
| * |
| * @return Integer value this node contains, if any; 0 for non-number |
| * nodes. |
| */ |
| public int intValue() { return 0; } |
| |
| /** |
| * Returns 64-bit long value for this node, <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns 0. |
| * For floating-point numbers, value is truncated using default |
| * Java coercion, similar to how cast from double to long operates. |
| * |
| * @return Long value this node contains, if any; 0 for non-number |
| * nodes. |
| */ |
| public long longValue() { return 0L; } |
| |
| /** |
| * Returns 32-bit floating value for this node, <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns 0.0. |
| * For integer values, conversion is done using coercion; this means |
| * that an overflow is possible for `long` values |
| * |
| * @return 32-bit float value this node contains, if any; 0.0 for non-number nodes. |
| * |
| * @since 2.2 |
| */ |
| public float floatValue() { return 0.0f; } |
| |
| /** |
| * Returns 64-bit floating point (double) value for this node, <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns 0.0. |
| * For integer values, conversion is done using coercion; this may result |
| * in overflows with {@link BigInteger} values. |
| * |
| * @return 64-bit double value this node contains, if any; 0.0 for non-number nodes. |
| * |
| * @since 2.2 |
| */ |
| public double doubleValue() { return 0.0; } |
| |
| /** |
| * Returns floating point value for this node (as {@link BigDecimal}), <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns <code>BigDecimal.ZERO</code>. |
| * |
| * @return {@link BigDecimal} value this node contains, if numeric node; <code>BigDecimal.ZERO</code> for non-number nodes. |
| */ |
| public BigDecimal decimalValue() { return BigDecimal.ZERO; } |
| |
| /** |
| * Returns integer value for this node (as {@link BigDecimal}), <b>if and only if</b> |
| * this node is numeric ({@link #isNumber} returns true). For other |
| * types returns <code>BigInteger.ZERO</code>. |
| * |
| * @return {@link BigInteger} value this node contains, if numeric node; <code>BigInteger.ZERO</code> for non-number nodes. |
| */ |
| public BigInteger bigIntegerValue() { return BigInteger.ZERO; } |
| |
| /* |
| /********************************************************** |
| /* Public API, value access with conversion(s)/coercion(s) |
| /********************************************************** |
| */ |
| |
| /** |
| * Method that will return a valid String representation of |
| * the container value, if the node is a value node |
| * (method {@link #isValueNode} returns true), |
| * otherwise empty String. |
| */ |
| public abstract String asText(); |
| |
| /** |
| * Method similar to {@link #asText()}, except that it will return |
| * <code>defaultValue</code> in cases where null value would be returned; |
| * either for missing nodes (trying to access missing property, or element |
| * at invalid item for array) or explicit nulls. |
| * |
| * @since 2.4 |
| */ |
| public String asText(String defaultValue) { |
| String str = asText(); |
| return (str == null) ? defaultValue : str; |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>int</b>. |
| * Numbers are coerced using default Java rules; booleans convert to 0 (false) |
| * and 1 (true), and Strings are parsed using default Java language integer |
| * parsing rules. |
| *<p> |
| * If representation can not be converted to an int (including structured types |
| * like Objects and Arrays), |
| * default value of <b>0</b> will be returned; no exceptions are thrown. |
| */ |
| public int asInt() { |
| return asInt(0); |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>int</b>. |
| * Numbers are coerced using default Java rules; booleans convert to 0 (false) |
| * and 1 (true), and Strings are parsed using default Java language integer |
| * parsing rules. |
| *<p> |
| * If representation can not be converted to an int (including structured types |
| * like Objects and Arrays), |
| * specified <b>defaultValue</b> will be returned; no exceptions are thrown. |
| */ |
| public int asInt(int defaultValue) { |
| return defaultValue; |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>long</b>. |
| * Numbers are coerced using default Java rules; booleans convert to 0 (false) |
| * and 1 (true), and Strings are parsed using default Java language integer |
| * parsing rules. |
| *<p> |
| * If representation can not be converted to an long (including structured types |
| * like Objects and Arrays), |
| * default value of <b>0</b> will be returned; no exceptions are thrown. |
| */ |
| public long asLong() { |
| return asLong(0L); |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>long</b>. |
| * Numbers are coerced using default Java rules; booleans convert to 0 (false) |
| * and 1 (true), and Strings are parsed using default Java language integer |
| * parsing rules. |
| *<p> |
| * If representation can not be converted to an long (including structured types |
| * like Objects and Arrays), |
| * specified <b>defaultValue</b> will be returned; no exceptions are thrown. |
| */ |
| public long asLong(long defaultValue) { |
| return defaultValue; |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>double</b>. |
| * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) |
| * and 1.0 (true), and Strings are parsed using default Java language integer |
| * parsing rules. |
| *<p> |
| * If representation can not be converted to an int (including structured types |
| * like Objects and Arrays), |
| * default value of <b>0.0</b> will be returned; no exceptions are thrown. |
| */ |
| public double asDouble() { |
| return asDouble(0.0); |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>double</b>. |
| * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) |
| * and 1.0 (true), and Strings are parsed using default Java language integer |
| * parsing rules. |
| *<p> |
| * If representation can not be converted to an int (including structured types |
| * like Objects and Arrays), |
| * specified <b>defaultValue</b> will be returned; no exceptions are thrown. |
| */ |
| public double asDouble(double defaultValue) { |
| return defaultValue; |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>boolean</b>. |
| * JSON booleans map naturally; integer numbers other than 0 map to true, and |
| * 0 maps to false |
| * and Strings 'true' and 'false' map to corresponding values. |
| *<p> |
| * If representation can not be converted to a boolean value (including structured types |
| * like Objects and Arrays), |
| * default value of <b>false</b> will be returned; no exceptions are thrown. |
| */ |
| public boolean asBoolean() { |
| return asBoolean(false); |
| } |
| |
| /** |
| * Method that will try to convert value of this node to a Java <b>boolean</b>. |
| * JSON booleans map naturally; integer numbers other than 0 map to true, and |
| * 0 maps to false |
| * and Strings 'true' and 'false' map to corresponding values. |
| *<p> |
| * If representation can not be converted to a boolean value (including structured types |
| * like Objects and Arrays), |
| * specified <b>defaultValue</b> will be returned; no exceptions are thrown. |
| */ |
| public boolean asBoolean(boolean defaultValue) { |
| return defaultValue; |
| } |
| |
| /* |
| /********************************************************** |
| /* Public API, value find / existence check methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Method that allows checking whether this node is JSON Object node |
| * and contains value for specified property. If this is the case |
| * (including properties with explicit null values), returns true; |
| * otherwise returns false. |
| *<p> |
| * This method is equivalent to: |
| *<pre> |
| * node.get(fieldName) != null |
| *</pre> |
| * (since return value of get() is node, not value node contains) |
| *<p> |
| * NOTE: when explicit <code>null</code> values are added, this |
| * method will return <code>true</code> for such properties. |
| * |
| * @param fieldName Name of element to check |
| * |
| * @return True if this node is a JSON Object node, and has a property |
| * entry with specified name (with any value, including null value) |
| */ |
| public boolean has(String fieldName) { |
| return get(fieldName) != null; |
| } |
| |
| /** |
| * Method that allows checking whether this node is JSON Array node |
| * and contains a value for specified index |
| * If this is the case |
| * (including case of specified indexing having null as value), returns true; |
| * otherwise returns false. |
| *<p> |
| * Note: array element indexes are 0-based. |
| *<p> |
| * This method is equivalent to: |
| *<pre> |
| * node.get(index) != null |
| *</pre> |
| *<p> |
| * NOTE: this method will return <code>true</code> for explicitly added |
| * null values. |
| * |
| * @param index Index to check |
| * |
| * @return True if this node is a JSON Object node, and has a property |
| * entry with specified name (with any value, including null value) |
| */ |
| public boolean has(int index) { |
| return get(index) != null; |
| } |
| |
| /** |
| * Method that is similar to {@link #has(String)}, but that will |
| * return <code>false</code> for explicitly added nulls. |
| *<p> |
| * This method is functionally equivalent to: |
| *<pre> |
| * node.get(fieldName) != null << !node.get(fieldName).isNull() |
| *</pre> |
| * |
| * @since 2.1 |
| */ |
| public boolean hasNonNull(String fieldName) { |
| JsonNode n = get(fieldName); |
| return (n != null) && !n.isNull(); |
| } |
| |
| /** |
| * Method that is similar to {@link #has(int)}, but that will |
| * return <code>false</code> for explicitly added nulls. |
| *<p> |
| * This method is equivalent to: |
| *<pre> |
| * node.get(index) != null << !node.get(index).isNull() |
| *</pre> |
| * |
| * @since 2.1 |
| */ |
| public boolean hasNonNull(int index) { |
| JsonNode n = get(index); |
| return (n != null) && !n.isNull(); |
| } |
| |
| /* |
| /********************************************************** |
| /* Public API, container access |
| /********************************************************** |
| */ |
| |
| /** |
| * Same as calling {@link #elements}; implemented so that |
| * convenience "for-each" loop can be used for looping over elements |
| * of JSON Array constructs. |
| */ |
| @Override |
| public final Iterator<JsonNode> iterator() { return elements(); } |
| |
| /** |
| * Method for accessing all value nodes of this Node, iff |
| * this node is a JSON Array or Object node. In case of Object node, |
| * field names (keys) are not included, only values. |
| * For other types of nodes, returns empty iterator. |
| */ |
| public Iterator<JsonNode> elements() { |
| return ClassUtil.emptyIterator(); |
| } |
| |
| /** |
| * @return Iterator that can be used to traverse all key/value pairs for |
| * object nodes; empty iterator (no contents) for other types |
| */ |
| public Iterator<Map.Entry<String, JsonNode>> fields() { |
| return ClassUtil.emptyIterator(); |
| } |
| |
| /* |
| /********************************************************** |
| /* Public API, find methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Method for finding a JSON Object field with specified name in this |
| * node or its child nodes, and returning value it has. |
| * If no matching field is found in this node or its descendants, returns null. |
| * |
| * @param fieldName Name of field to look for |
| * |
| * @return Value of first matching node found, if any; null if none |
| */ |
| public abstract JsonNode findValue(String fieldName); |
| |
| /** |
| * Method for finding JSON Object fields with specified name, and returning |
| * found ones as a List. Note that sub-tree search ends if a field is found, |
| * so possible children of result nodes are <b>not</b> included. |
| * If no matching fields are found in this node or its descendants, returns |
| * an empty List. |
| * |
| * @param fieldName Name of field to look for |
| */ |
| public final List<JsonNode> findValues(String fieldName) |
| { |
| List<JsonNode> result = findValues(fieldName, null); |
| if (result == null) { |
| return Collections.emptyList(); |
| } |
| return result; |
| } |
| |
| /** |
| * Similar to {@link #findValues}, but will additionally convert |
| * values into Strings, calling {@link #asText}. |
| */ |
| public final List<String> findValuesAsText(String fieldName) |
| { |
| List<String> result = findValuesAsText(fieldName, null); |
| if (result == null) { |
| return Collections.emptyList(); |
| } |
| return result; |
| } |
| |
| /** |
| * Method similar to {@link #findValue}, but that will return a |
| * "missing node" instead of null if no field is found. Missing node |
| * is a specific kind of node for which {@link #isMissingNode} |
| * returns true; and all value access methods return empty or |
| * missing value. |
| * |
| * @param fieldName Name of field to look for |
| * |
| * @return Value of first matching node found; or if not found, a |
| * "missing node" (non-null instance that has no value) |
| */ |
| public abstract JsonNode findPath(String fieldName); |
| |
| /** |
| * Method for finding a JSON Object that contains specified field, |
| * within this node or its descendants. |
| * If no matching field is found in this node or its descendants, returns null. |
| * |
| * @param fieldName Name of field to look for |
| * |
| * @return Value of first matching node found, if any; null if none |
| */ |
| public abstract JsonNode findParent(String fieldName); |
| |
| /** |
| * Method for finding a JSON Object that contains specified field, |
| * within this node or its descendants. |
| * If no matching field is found in this node or its descendants, returns null. |
| * |
| * @param fieldName Name of field to look for |
| * |
| * @return Value of first matching node found, if any; null if none |
| */ |
| public final List<JsonNode> findParents(String fieldName) |
| { |
| List<JsonNode> result = findParents(fieldName, null); |
| if (result == null) { |
| return Collections.emptyList(); |
| } |
| return result; |
| } |
| |
| public abstract List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar); |
| public abstract List<String> findValuesAsText(String fieldName, List<String> foundSoFar); |
| public abstract List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar); |
| |
| /* |
| /********************************************************** |
| /* Public API, path handling |
| /********************************************************** |
| */ |
| |
| /** |
| * Method that can be called on Object nodes, to access a property |
| * that has Object value; or if no such property exists, to create, |
| * add and return such Object node. |
| * If the node method is called on is not Object node, |
| * or if property exists and has value that is not Object node, |
| * {@link UnsupportedOperationException} is thrown |
| */ |
| public JsonNode with(String propertyName) { |
| throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " |
| +getClass().getName()+"), can not call with() on it"); |
| } |
| |
| /** |
| * Method that can be called on Object nodes, to access a property |
| * that has <code>Array</code> value; or if no such property exists, to create, |
| * add and return such Array node. |
| * If the node method is called on is not Object node, |
| * or if property exists and has value that is not Array node, |
| * {@link UnsupportedOperationException} is thrown |
| */ |
| public JsonNode withArray(String propertyName) { |
| throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " |
| +getClass().getName()+"), can not call withArray() on it"); |
| } |
| |
| /* |
| /********************************************************** |
| /* Public API, comparison |
| /********************************************************** |
| */ |
| |
| /** |
| * Entry method for invoking customizable comparison, using passed-in |
| * {@link Comparator} object. Nodes will handle traversal of structured |
| * types (arrays, objects), but defer to comparator for scalar value |
| * comparisons. If a "natural" {@link Comparator} is passed -- one that |
| * simply calls <code>equals()</code> on one of arguments, passing the other |
| * -- implementation is the same as directly calling <code>equals()</code> |
| * on node. |
| *<p> |
| * Default implementation simply delegates to passed in <code>comparator</code>, |
| * with <code>this</code> as the first argument, and <code>other</code> as |
| * the second argument. |
| * |
| * @param comparator Object called to compare two scalar {@link JsonNode} |
| * instances, and return either 0 (are equals) or non-zero (not equal) |
| * |
| * @since 2.6 |
| */ |
| public boolean equals(Comparator<JsonNode> comparator, JsonNode other) { |
| return comparator.compare(this, other) == 0; |
| } |
| |
| /* |
| /********************************************************** |
| /* Overridden standard methods |
| /********************************************************** |
| */ |
| |
| /** |
| * Method that will produce developer-readable representation of the |
| * node; which may <b>or may not</b> be as valid JSON. |
| * If you want valid JSON output (or output formatted using one of |
| * other Jackson supported data formats) make sure to use |
| * {@link ObjectMapper} or {@link ObjectWriter} to serialize an |
| * instance, for example: |
| *<pre> |
| * String json = objectMapper.writeValueAsString(rootNode); |
| *</pre> |
| *<p> |
| * Note: method defined as abstract to ensure all implementation |
| * classes explicitly implement method, instead of relying |
| * on {@link Object#toString()} definition. |
| */ |
| @Override |
| public abstract String toString(); |
| |
| /** |
| * Equality for node objects is defined as full (deep) value |
| * equality. This means that it is possible to compare complete |
| * JSON trees for equality by comparing equality of root nodes. |
| *<p> |
| * Note: marked as abstract to ensure all implementation |
| * classes define it properly and not rely on definition |
| * from {@link java.lang.Object}. |
| */ |
| @Override |
| public abstract boolean equals(Object o); |
| } |