Skip to content

Commit

Permalink
feat: Add ToJson for DynamoDBEvent (#1685)
Browse files Browse the repository at this point in the history
  • Loading branch information
ashovlin authored Mar 4, 2024
1 parent 95a6a94 commit 9a7443a
Show file tree
Hide file tree
Showing 6 changed files with 610 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<TargetFrameworks>netcoreapp3.1;net8.0</TargetFrameworks>
<Description>Amazon Lambda .NET Core support - DynamoDBEvents package.</Description>
<AssemblyTitle>Amazon.Lambda.DynamoDBEvents</AssemblyTitle>
<VersionPrefix>3.0.0</VersionPrefix>
<VersionPrefix>3.1.0</VersionPrefix>
<AssemblyName>Amazon.Lambda.DynamoDBEvents</AssemblyName>
<PackageId>Amazon.Lambda.DynamoDBEvents</PackageId>
<PackageTags>AWS;Amazon;Lambda</PackageTags>
Expand Down
157 changes: 157 additions & 0 deletions Libraries/src/Amazon.Lambda.DynamoDBEvents/ExtensionMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
using static Amazon.Lambda.DynamoDBEvents.DynamoDBEvent;

namespace Amazon.Lambda.DynamoDBEvents
{
/// <summary>
/// Extension methods for working with <see cref="DynamoDBEvent"/>
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Converts a dictionary representing a DynamoDB item to a JSON string.
/// This may be useful when casting a DynamoDB Lambda event to the AWS SDK's
/// higher-level document and object persistence classes.
/// </summary>
/// <param name="item">Dictionary representing a DynamoDB item</param>
/// <returns>Unformatted JSON string representing the DynamoDB item</returns>
public static string ToJson(this Dictionary<string, AttributeValue> item)
{
return ToJson(item, false);
}

/// <summary>
/// Converts a dictionary representing a DynamoDB item to a JSON string.
/// This may be useful when casting a DynamoDB Lambda event to the AWS SDK's
/// higher-level document and object persistence classes.
/// </summary>
/// <param name="item">Dictionary representing a DynamoDB item</param>
/// <returns>Formatted JSON string representing the DynamoDB item</returns>
public static string ToJsonPretty(this Dictionary<string, AttributeValue> item)
{
return ToJson(item, true);
}

/// <summary>
/// Internal entry point for converting a dictionary representing a DynamoDB item to a JSON string.
/// </summary>
/// <param name="item">Dictionary representing a DynamoDB item</param>
/// <param name="prettyPrint">Whether the resulting JSON should be formatted</param>
/// <returns>JSON string representing the DynamoDB item</returns>
private static string ToJson(Dictionary<string, AttributeValue> item, bool prettyPrint)
{
if (item == null || item.Count == 0)
{
return "{}";
}

using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = prettyPrint});

WriteJson(writer, item);

writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}

/// <summary>
/// Writes a single DynamoDB attribute as a json. May be called recursively for maps.
/// </summary>
/// <param name="writer">JSON writer</param>
/// <param name="item">Dictionary representing a DynamoDB item, or a map within an item</param>
private static void WriteJson(Utf8JsonWriter writer, Dictionary<string, AttributeValue> item)
{
writer.WriteStartObject();

foreach (var attribute in item)
{
writer.WritePropertyName(attribute.Key);
WriteJsonValue(writer, attribute.Value);
}

writer.WriteEndObject();
}

/// <summary>
/// Writes a single DynamoDB attribute value as a json value
/// </summary>
/// <param name="writer">JSON writer</param>
/// <param name="attribute">DynamoDB attribute</param>
private static void WriteJsonValue(Utf8JsonWriter writer, AttributeValue attribute)
{
if (attribute.S != null)
{
writer.WriteStringValue(attribute.S);
}
else if (attribute.N != null)
{
#if NETCOREAPP3_1 // WriteRawValue was added in .NET 6, but we need to write out Number values without quotes
using var document = JsonDocument.Parse(attribute.N);
document.WriteTo(writer);
#else
writer.WriteRawValue(attribute.N);
#endif
}
else if (attribute.B != null)
{
writer.WriteBase64StringValue(attribute.B.ToArray());
}
else if (attribute.BOOL != null)
{
writer.WriteBooleanValue(attribute.BOOL.Value);
}
else if (attribute.NULL != null)
{
writer.WriteNullValue();
}
else if (attribute.M != null)
{
WriteJson(writer, attribute.M);
}
else if (attribute.L != null)
{
writer.WriteStartArray();
foreach (var item in attribute.L)
{
WriteJsonValue(writer, item);
}
writer.WriteEndArray();
}
else if (attribute.SS != null)
{
writer.WriteStartArray();
foreach (var item in attribute.SS)
{
writer.WriteStringValue(item);
}
writer.WriteEndArray();
}
else if (attribute.NS != null)
{
writer.WriteStartArray();
foreach (var item in attribute.NS)
{
#if NETCOREAPP3_1 // WriteRawValue was added in .NET 6, but we need to write out Number values without quotes
using var document = JsonDocument.Parse(item);
document.WriteTo(writer);
#else
writer.WriteRawValue(item);
#endif
}
writer.WriteEndArray();
}
else if (attribute.BS != null)
{
writer.WriteStartArray();
foreach (var item in attribute.BS)
{
writer.WriteBase64StringValue(item.ToArray());
}
writer.WriteEndArray();
}
}
}
}
4 changes: 3 additions & 1 deletion Libraries/test/EventsTests.NET6/EventsTests.NET6.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<PackageId>EventsTests31</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<RootNamespace>EventsTests.NET6</RootNamespace>
<LangVersion>latest</LangVersion>
</PropertyGroup>


Expand Down Expand Up @@ -54,13 +55,14 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.301.14" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="AWSSDK.Core" Version="3.7.10.9" />
<PackageReference Include="AWSSDK.Core" Version="3.7.302.13" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<RuntimeIdentifiers>win7-x64;win7-x86</RuntimeIdentifiers>
<RootNamespace>EventsTests31</RootNamespace>
<LangVersion>latest</LangVersion>
</PropertyGroup>


Expand Down Expand Up @@ -54,10 +55,11 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.301.14" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="AWSSDK.Core" Version="3.7.10.9" />
<PackageReference Include="AWSSDK.Core" Version="3.7.302.13" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 9a7443a

Please sign in to comment.