/// <summary> /// The <see cref="Serialize(object?,DynamoSerializerOptions)"/> method serializes an object to a DynamoDB attribute value. /// </summary> /// <param name="value">The object to serialize.</param> /// <param name="options">The serialization options to use.</param> /// <returns>A DynamoDB attribute value or <c>null</c> when the object state cannot be represented in DynamoDB.</returns> public static AttributeValue?Serialize(object?value, DynamoSerializerOptions options) { // check for types mapped to attribute type 'NULL' if (value is null) { return(new AttributeValue { NULL = true }); } // find a suiteable converter for the provided type var typeToConvert = value.GetType(); var converter = options.GetConverters().FirstOrDefault(converter => converter.CanConvert(typeToConvert)); if (converter is null) { throw new DynamoSerializationException($"cannot convert value of type '{typeToConvert?.FullName ?? "<null>"}'"); } return(converter.ToAttributeValue(value, typeToConvert, options)); }
/// <summary> /// The <see cref="Deserialize(Dictionary{string, AttributeValue},Type,DynamoSerializerOptions)"/> method deserializes a DynamoDB document into a <paramref name="targetType"/> instance. /// </summary> /// <param name="document">The DynamoDB document to deserialize.</param> /// <param name="targetType">The type to deserialize into.</param> /// <param name="options">The deserialization options to use.</param> /// <returns>An instance of <paramref name="targetType"/> or <c>null</c> when the DynamoDB document is <c>null</c>.</returns> public static object?Deserialize(Dictionary <string, AttributeValue> document, Type?targetType, DynamoSerializerOptions options) { var usedTargetType = ((targetType is null) || (targetType == typeof(object))) ? typeof(Dictionary <string, object>) : targetType; var converter = options.GetConverters().FirstOrDefault(converter => converter.CanConvert(usedTargetType)); if (converter == null) { throw new DynamoSerializationException($"cannot convert document {nameof(AttributeValue.M)} (given: {targetType?.FullName ?? "<null>"})"); } return(converter.FromMap(document, usedTargetType, options)); }
/// <summary> /// The <see cref="Deserialize(AttributeValue,Type,DynamoSerializerOptions)"/> method deserializes a DynamoDB attribute value into a <paramref name="targetType"/> instance. /// </summary> /// <param name="attribute">The DynamoDB attribute value to deserialize.</param> /// <param name="targetType">The type to deserialize into.</param> /// <param name="options">The deserialization options to use.</param> /// <returns>An instance of <paramref name="targetType"/> or <c>null</c> when the DynamoDB attribute value is <c>NULL</c>.</returns> public static object?Deserialize(AttributeValue?attribute, Type?targetType, DynamoSerializerOptions options) { // handle missing value if (attribute == null) { return(FindConverter(typeof(object), "<default>", (converter, usedTargetType) => converter.GetDefaultValue(usedTargetType, options))); } // handle boolean value if (attribute.IsBOOLSet) { return(FindConverter(typeof(bool), nameof(AttributeValue.BOOL), (converter, usedTargetType) => converter.FromBool(attribute.BOOL, usedTargetType, options))); } // handle string value if (!(attribute.S is null)) { return(FindConverter(typeof(string), nameof(AttributeValue.S), (converter, usedTargetType) => converter.FromString(attribute.S, usedTargetType, options))); } // handle number value if (!(attribute.N is null)) { return(FindConverter(typeof(double), nameof(AttributeValue.N), (converter, usedTargetType) => converter.FromNumber(attribute.N, usedTargetType, options))); } // handle binary value if (!(attribute.B is null)) { return(FindConverter(typeof(byte[]), nameof(AttributeValue.B), (converter, usedTargetType) => converter.FromBinary(attribute.B, usedTargetType, options))); } // handle list value if (attribute.IsLSet) { return(FindConverter(typeof(List <object>), nameof(AttributeValue.L), (converter, usedTargetType) => converter.FromList(attribute.L, usedTargetType, options))); } // handle map value if (attribute.IsMSet) { return(Deserialize(attribute.M, targetType, options)); } // handle binary set value if (attribute.BS.Any()) { return(FindConverter(typeof(HashSet <byte[]>), nameof(AttributeValue.BS), (converter, usedTargetType) => converter.FromBinarySet(attribute.BS, usedTargetType, options))); } // handle string set value if (attribute.SS.Any()) { return(FindConverter(typeof(HashSet <string>), nameof(AttributeValue.SS), (converter, usedTargetType) => converter.FromStringSet(attribute.SS, usedTargetType, options))); } // handle number set value if (attribute.NS.Any()) { return(FindConverter(typeof(HashSet <double>), nameof(AttributeValue.NS), (converter, usedTargetType) => converter.FromNumberSet(attribute.NS, usedTargetType, options))); } // handle null value if (attribute.NULL) { return(FindConverter(typeof(object), nameof(AttributeValue.NULL), (converter, usedTargetType) => converter.FromNull(usedTargetType, options))); } throw new DynamoSerializationException($"invalid attribute value"); // local functions object?FindConverter(Type defaultType, string attributeValueTypeName, Func <IDynamoAttributeConverter, Type, object?> convert) { var usedTargetType = ((targetType is null) || (targetType == typeof(object))) ? defaultType : targetType; var converter = options.GetConverters().FirstOrDefault(converter => converter.CanConvert(usedTargetType)); if (converter == null) { throw new DynamoSerializationException($"cannot convert attribute value {attributeValueTypeName} (given: {targetType?.FullName ?? "<null>"})"); } return(convert(converter, usedTargetType)); } }
/// <summary> /// The <see cref="Deserialize(Dictionary{string, AttributeValue},DynamoSerializerOptions)"/> method deserializes a DynamoDB document into a <typeparamref name="TRecord"/> instance. /// </summary> /// <param name="document">The DynamoDB document to deserialize.</param> /// <param name="options">The deserialization options to use.</param> /// <typeparam name="TRecord">The type to deserialize into.</typeparam> /// <returns>An instance of <typeparamref name="TRecord"/> or <c>null</c> when the DynamoDB document is <c>null</c>.</returns> public static TRecord?Deserialize <TRecord>(Dictionary <string, AttributeValue> document, DynamoSerializerOptions options) where TRecord : class => (TRecord?)Deserialize(document, typeof(TRecord), options);