/* * Copyright 2016-2017 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. * You may obtain a copy of the License at: * * http://aws.amazon.com/apache2.0 * * 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 com.amazonaws.services.dynamodbv2.datamodeling; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; /** * A simple JSON converter that uses the Jackson JSON processor. * * <p>It shares all limitations of that library. For more information about * Jackson, see: http://wiki.fasterxml.com/JacksonHome</p> * * <pre class="brush: java"> * @DynamoDBTypeConvertedJson * public Currency getCurrency() * </pre> * * <p>Where,</p> * <pre class="brush: java"> * public class Currency { * private Double amount; * private String unit; * * public Double getAmount() { return amount; } * public void setAmount(Double amount) { this.amount = amount; } * * public String getUnit() { return unit; } * public void setUnit(String unit) { this.unit = unit; } * } * </pre> * * <p>Would write the following value to DynamoDB given,</p> * <ul> * <li><code>Currency(79.99,"USD")</code> = <code> "{\"amount\":79.99,\"unit\":\"USD\"}"</code></li> * </ul> * * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverted */ @DynamoDBTypeConverted(converter=DynamoDBTypeConvertedJson.Converter.class) @DynamoDBTyped(DynamoDBMapperFieldModel.DynamoDBAttributeType.S) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) public @interface DynamoDBTypeConvertedJson { /** * The value type to use when calling the JSON mapper's {@code readValue}; * a value of {@code Void.class} indicates to use the getter's type. */ Class<? extends Object> targetType() default void.class; /** * JSON type converter. */ final class Converter<T> implements DynamoDBTypeConverter<String,T> { private static final ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); private final Class<T> targetType; public Converter(Class<T> targetType, DynamoDBTypeConvertedJson annotation) { this.targetType = annotation.targetType() == void.class ? targetType : (Class<T>)annotation.targetType(); } @Override public final String convert(final T object) { try { return mapper.writeValueAsString(object); } catch (final Exception e) { throw new DynamoDBMappingException("Unable to write object to JSON", e); } } @Override public final T unconvert(final String object) { try { return mapper.readValue(object, targetType); } catch (final Exception e) { throw new DynamoDBMappingException("Unable to read JSON string", e); } } } }