1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.protocols.jsoncore; 17 18 import java.util.Collections; 19 import java.util.List; 20 import java.util.Map; 21 import java.util.Optional; 22 import software.amazon.awssdk.annotations.SdkProtectedApi; 23 import software.amazon.awssdk.protocols.jsoncore.internal.ObjectJsonNode; 24 import software.amazon.awssdk.thirdparty.jackson.core.JsonFactory; 25 26 /** 27 * A node in a JSON document. Either a number, string, boolean, array, object or null. Also can be an embedded object, 28 * which is a non-standard type used in JSON extensions, like CBOR. 29 * 30 * <p>Created from a JSON document via {@link #parser()} or {@link #parserBuilder()}. 31 * 32 * <p>The type of node can be determined using "is" methods like {@link #isNumber()} and {@link #isString()}. 33 * Once the type is determined, the value of the node can be extracted via the "as" methods, like {@link #asNumber()} 34 * and {@link #asString()}. 35 */ 36 @SdkProtectedApi 37 public interface JsonNode { 38 /** 39 * Create a {@link JsonNodeParser} for generating a {@link JsonNode} from a JSON document. 40 */ parser()41 static JsonNodeParser parser() { 42 return JsonNodeParser.create(); 43 } 44 45 /** 46 * Create a {@link JsonNodeParser.Builder} for generating a {@link JsonNode} from a JSON document. 47 */ parserBuilder()48 static JsonNodeParser.Builder parserBuilder() { 49 return JsonNodeParser.builder(); 50 } 51 52 /** 53 * Return an empty object node. 54 */ emptyObjectNode()55 static JsonNode emptyObjectNode() { 56 return new ObjectJsonNode(Collections.emptyMap()); 57 } 58 59 /** 60 * Returns true if this node represents a JSON number: https://datatracker.ietf.org/doc/html/rfc8259#section-6 61 * 62 * @see #asNumber() 63 */ isNumber()64 default boolean isNumber() { 65 return false; 66 } 67 68 /** 69 * Returns true if this node represents a JSON string: https://datatracker.ietf.org/doc/html/rfc8259#section-7 70 * 71 * @see #asString() 72 */ isString()73 default boolean isString() { 74 return false; 75 } 76 77 /** 78 * Returns true if this node represents a JSON boolean: https://datatracker.ietf.org/doc/html/rfc8259#section-3 79 * 80 * @see #asBoolean() 81 */ isBoolean()82 default boolean isBoolean() { 83 return false; 84 } 85 86 /** 87 * Returns true if this node represents a JSON null: https://datatracker.ietf.org/doc/html/rfc8259#section-3 88 */ isNull()89 default boolean isNull() { 90 return false; 91 } 92 93 /** 94 * Returns true if this node represents a JSON array: https://datatracker.ietf.org/doc/html/rfc8259#section-5 95 * 96 * @see #asArray() 97 */ isArray()98 default boolean isArray() { 99 return false; 100 } 101 102 /** 103 * Returns true if this node represents a JSON object: https://datatracker.ietf.org/doc/html/rfc8259#section-4 104 * 105 * @see #asObject() 106 */ isObject()107 default boolean isObject() { 108 return false; 109 } 110 111 /** 112 * Returns true if this node represents a JSON "embedded object". This non-standard type is associated with JSON extensions, 113 * like CBOR or ION. It allows additional data types to be embedded in a JSON document, like a timestamp or a raw byte array. 114 * 115 * <p>Users who are only concerned with handling JSON can ignore this field. It will only be present when using a custom 116 * {@link JsonFactory} via {@link JsonNodeParser.Builder#jsonFactory(JsonFactory)}. 117 * 118 * @see #asEmbeddedObject() 119 */ isEmbeddedObject()120 default boolean isEmbeddedObject() { 121 return false; 122 } 123 124 /** 125 * When {@link #isNumber()} is true, this returns the number associated with this node. This will throw an exception if 126 * {@link #isNumber()} is false. 127 * 128 * @see #text() 129 */ asNumber()130 String asNumber(); 131 132 /** 133 * When {@link #isString()}, is true, this returns the string associated with this node. This will throw an exception if 134 * {@link #isString()} ()} is false. 135 */ asString()136 String asString(); 137 138 /** 139 * When {@link #isBoolean()} is true, this returns the boolean associated with this node. This will throw an exception if 140 * {@link #isBoolean()} is false. 141 */ asBoolean()142 boolean asBoolean(); 143 144 /** 145 * When {@link #isArray()} is true, this returns the array associated with this node. This will throw an exception if 146 * {@link #isArray()} is false. 147 */ asArray()148 List<JsonNode> asArray(); 149 150 /** 151 * When {@link #isObject()} is true, this returns the object associated with this node. This will throw an exception if 152 * {@link #isObject()} is false. 153 */ asObject()154 Map<String, JsonNode> asObject(); 155 156 /** 157 * When {@link #isEmbeddedObject()} is true, this returns the embedded object associated with this node. This will throw 158 * an exception if {@link #isEmbeddedObject()} is false. 159 * 160 * @see #isEmbeddedObject() 161 */ asEmbeddedObject()162 Object asEmbeddedObject(); 163 164 /** 165 * Visit this node using the provided visitor. 166 */ visit(JsonNodeVisitor<T> visitor)167 <T> T visit(JsonNodeVisitor<T> visitor); 168 169 /** 170 * When {@link #isString()}, {@link #isBoolean()}, or {@link #isNumber()} is true, this will return the value of this node 171 * as a textual string. If this is any other type, this will return null. 172 */ text()173 String text(); 174 175 /** 176 * When {@link #isObject()} is true, this will return the result of {@code Optional.ofNullable(asObject().get(child))}. If 177 * this is any other type, this will return {@link Optional#empty()}. 178 */ field(String child)179 default Optional<JsonNode> field(String child) { 180 return Optional.empty(); 181 } 182 183 /** 184 * When {@link #isArray()} is true, this will return the result of {@code asArray().get(child)} if child is within bounds. If 185 * this is any other type or the child is out of bounds, this will return {@link Optional#empty()}. 186 */ index(int child)187 default Optional<JsonNode> index(int child) { 188 return Optional.empty(); 189 } 190 } 191