
software.amazon.awssdk.protocols.json.internal.unmarshall.JsonProtocolUnmarshaller Maven / Gradle / Ivy
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package software.amazon.awssdk.protocols.json.internal.unmarshall;
import static software.amazon.awssdk.protocols.core.StringToValueConverter.TO_SDK_BYTES;
import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.core.SdkField;
import software.amazon.awssdk.core.SdkPojo;
import software.amazon.awssdk.core.document.Document;
import software.amazon.awssdk.core.protocol.MarshallLocation;
import software.amazon.awssdk.core.protocol.MarshallingType;
import software.amazon.awssdk.core.traits.ListTrait;
import software.amazon.awssdk.core.traits.MapTrait;
import software.amazon.awssdk.core.traits.PayloadTrait;
import software.amazon.awssdk.core.traits.TimestampFormatTrait;
import software.amazon.awssdk.core.traits.TraitType;
import software.amazon.awssdk.http.AbortableInputStream;
import software.amazon.awssdk.http.SdkHttpFullResponse;
import software.amazon.awssdk.protocols.core.StringToInstant;
import software.amazon.awssdk.protocols.core.StringToValueConverter;
import software.amazon.awssdk.protocols.json.internal.AwsStructuredPlainJsonFactory;
import software.amazon.awssdk.protocols.json.internal.MarshallerUtil;
import software.amazon.awssdk.protocols.json.internal.unmarshall.document.DocumentUnmarshaller;
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser;
import software.amazon.awssdk.protocols.jsoncore.JsonValueNodeFactory;
import software.amazon.awssdk.utils.Lazy;
import software.amazon.awssdk.utils.builder.Buildable;
/**
* Unmarshaller implementation for both JSON RPC and REST JSON services. This class is thread-safe and it is recommended to reuse
* a single instance for best performance.
*/
@SdkInternalApi
@ThreadSafe
public class JsonProtocolUnmarshaller {
private static final Lazy DEFAULT_DEPENDENCIES =
new Lazy<>(JsonProtocolUnmarshaller::newProtocolUnmarshallDependencies);
private final JsonUnmarshallerRegistry registry;
private final JsonUnmarshallingParser unmarshallingParser;
private final JsonNodeParser parser;
private JsonProtocolUnmarshaller(Builder builder) {
ProtocolUnmarshallDependencies dependencies = builder.protocolUnmarshallDependencies;
this.registry = dependencies.jsonUnmarshallerRegistry();
if (builder.enableFastUnmarshalling) {
this.unmarshallingParser = JsonUnmarshallingParser.builder()
.jsonValueNodeFactory(dependencies.nodeValueFactory())
.jsonFactory(dependencies.jsonFactory())
.unmarshallerRegistry(dependencies.jsonUnmarshallerRegistry())
.defaultTimestampFormat(dependencies.timestampFormats()
.get(MarshallLocation.PAYLOAD))
.build();
this.parser = null;
} else {
this.unmarshallingParser = null;
this.parser = createParser(builder, dependencies);
}
}
private JsonNodeParser createParser(Builder builder, ProtocolUnmarshallDependencies dependencies) {
if (builder.parser != null) {
return builder.parser;
}
return JsonNodeParser
.builder()
.jsonFactory(dependencies.jsonFactory())
.jsonValueNodeFactory(dependencies.nodeValueFactory())
.build();
}
public static DefaultProtocolUnmarshallDependencies defaultProtocolUnmarshallDependencies() {
return DEFAULT_DEPENDENCIES.getValue();
}
public static DefaultProtocolUnmarshallDependencies newProtocolUnmarshallDependencies() {
return DefaultProtocolUnmarshallDependencies.builder()
.jsonUnmarshallerRegistry(defaultJsonUnmarshallerRegistry())
.nodeValueFactory(JsonValueNodeFactory.DEFAULT)
.timestampFormats(defaultFormats())
.jsonFactory(AwsStructuredPlainJsonFactory.SDK_JSON_FACTORY.getJsonFactory())
.build();
}
private static Map defaultFormats() {
Map formats = new EnumMap<>(MarshallLocation.class);
formats.put(MarshallLocation.HEADER, TimestampFormatTrait.Format.RFC_822);
formats.put(MarshallLocation.PAYLOAD, TimestampFormatTrait.Format.UNIX_TIMESTAMP);
return Collections.unmodifiableMap(formats);
}
private static JsonUnmarshallerRegistry defaultJsonUnmarshallerRegistry() {
return timestampFormatRegistryFactory(defaultFormats());
}
public static DefaultJsonUnmarshallerRegistry createSharedRegistry() {
return DefaultJsonUnmarshallerRegistry
.builder()
.statusCodeUnmarshaller(MarshallingType.INTEGER, (context, json, f) -> context.response().statusCode())
.headerUnmarshaller(MarshallingType.STRING, HeaderUnmarshaller.STRING)
.headerUnmarshaller(MarshallingType.INTEGER, HeaderUnmarshaller.INTEGER)
.headerUnmarshaller(MarshallingType.LONG, HeaderUnmarshaller.LONG)
.headerUnmarshaller(MarshallingType.SHORT, HeaderUnmarshaller.SHORT)
.headerUnmarshaller(MarshallingType.DOUBLE, HeaderUnmarshaller.DOUBLE)
.headerUnmarshaller(MarshallingType.BOOLEAN, HeaderUnmarshaller.BOOLEAN)
.headerUnmarshaller(MarshallingType.FLOAT, HeaderUnmarshaller.FLOAT)
.headerUnmarshaller(MarshallingType.LIST, HeaderUnmarshaller.LIST)
.payloadUnmarshaller(MarshallingType.STRING, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_STRING))
.payloadUnmarshaller(MarshallingType.INTEGER, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_INTEGER))
.payloadUnmarshaller(MarshallingType.LONG, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_LONG))
.payloadUnmarshaller(MarshallingType.BYTE, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_BYTE))
.payloadUnmarshaller(MarshallingType.SHORT, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_SHORT))
.payloadUnmarshaller(MarshallingType.FLOAT, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_FLOAT))
.payloadUnmarshaller(MarshallingType.DOUBLE, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_DOUBLE))
.payloadUnmarshaller(MarshallingType.BIG_DECIMAL, new SimpleTypeJsonUnmarshaller<>(
StringToValueConverter.TO_BIG_DECIMAL))
.payloadUnmarshaller(MarshallingType.BOOLEAN, new SimpleTypeJsonUnmarshaller<>(StringToValueConverter.TO_BOOLEAN))
.payloadUnmarshaller(MarshallingType.SDK_BYTES, JsonProtocolUnmarshaller::unmarshallSdkBytes)
.payloadUnmarshaller(MarshallingType.SDK_POJO, JsonProtocolUnmarshaller::unmarshallStructured)
.payloadUnmarshaller(MarshallingType.LIST, JsonProtocolUnmarshaller::unmarshallList)
.payloadUnmarshaller(MarshallingType.MAP, JsonProtocolUnmarshaller::unmarshallMap)
.payloadUnmarshaller(MarshallingType.DOCUMENT, JsonProtocolUnmarshaller::unmarshallDocument)
.build();
}
private static SdkBytes unmarshallSdkBytes(JsonUnmarshallerContext context,
JsonNode jsonContent,
SdkField field) {
if (jsonContent == null || jsonContent.isNull()) {
return null;
}
// Binary protocols like CBOR may already have the raw bytes extracted.
if (jsonContent.isEmbeddedObject()) {
return SdkBytes.fromByteArray((byte[]) jsonContent.asEmbeddedObject());
} else {
// Otherwise decode the JSON string as Base64
return TO_SDK_BYTES.convert(jsonContent.text(), field);
}
}
private static SdkPojo unmarshallStructured(JsonUnmarshallerContext context, JsonNode jsonContent, SdkField f) {
if (jsonContent == null || jsonContent.isNull()) {
return null;
} else {
return unmarshallStructured(f.constructor().get(), jsonContent, context);
}
}
private static Document unmarshallDocument(JsonUnmarshallerContext context,
JsonNode jsonContent,
SdkField field) {
if (jsonContent == null) {
return null;
}
return jsonContent.isNull() ? Document.fromNull() : getDocumentFromJsonContent(jsonContent);
}
private static Document getDocumentFromJsonContent(JsonNode jsonContent) {
return jsonContent.visit(new DocumentUnmarshaller());
}
private static Map unmarshallMap(JsonUnmarshallerContext context,
JsonNode jsonContent,
SdkField
© 2015 - 2025 Weber Informatics LLC | Privacy Policy