Skip to content

Commit 9a7443a

Browse files
authored
feat: Add ToJson for DynamoDBEvent (#1685)
1 parent 95a6a94 commit 9a7443a

File tree

6 files changed

+610
-3
lines changed

6 files changed

+610
-3
lines changed

Libraries/src/Amazon.Lambda.DynamoDBEvents/Amazon.Lambda.DynamoDBEvents.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<TargetFrameworks>netcoreapp3.1;net8.0</TargetFrameworks>
77
<Description>Amazon Lambda .NET Core support - DynamoDBEvents package.</Description>
88
<AssemblyTitle>Amazon.Lambda.DynamoDBEvents</AssemblyTitle>
9-
<VersionPrefix>3.0.0</VersionPrefix>
9+
<VersionPrefix>3.1.0</VersionPrefix>
1010
<AssemblyName>Amazon.Lambda.DynamoDBEvents</AssemblyName>
1111
<PackageId>Amazon.Lambda.DynamoDBEvents</PackageId>
1212
<PackageTags>AWS;Amazon;Lambda</PackageTags>
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Text;
4+
using System.Text.Json;
5+
using static Amazon.Lambda.DynamoDBEvents.DynamoDBEvent;
6+
7+
namespace Amazon.Lambda.DynamoDBEvents
8+
{
9+
/// <summary>
10+
/// Extension methods for working with <see cref="DynamoDBEvent"/>
11+
/// </summary>
12+
public static class ExtensionMethods
13+
{
14+
/// <summary>
15+
/// Converts a dictionary representing a DynamoDB item to a JSON string.
16+
/// This may be useful when casting a DynamoDB Lambda event to the AWS SDK's
17+
/// higher-level document and object persistence classes.
18+
/// </summary>
19+
/// <param name="item">Dictionary representing a DynamoDB item</param>
20+
/// <returns>Unformatted JSON string representing the DynamoDB item</returns>
21+
public static string ToJson(this Dictionary<string, AttributeValue> item)
22+
{
23+
return ToJson(item, false);
24+
}
25+
26+
/// <summary>
27+
/// Converts a dictionary representing a DynamoDB item to a JSON string.
28+
/// This may be useful when casting a DynamoDB Lambda event to the AWS SDK's
29+
/// higher-level document and object persistence classes.
30+
/// </summary>
31+
/// <param name="item">Dictionary representing a DynamoDB item</param>
32+
/// <returns>Formatted JSON string representing the DynamoDB item</returns>
33+
public static string ToJsonPretty(this Dictionary<string, AttributeValue> item)
34+
{
35+
return ToJson(item, true);
36+
}
37+
38+
/// <summary>
39+
/// Internal entry point for converting a dictionary representing a DynamoDB item to a JSON string.
40+
/// </summary>
41+
/// <param name="item">Dictionary representing a DynamoDB item</param>
42+
/// <param name="prettyPrint">Whether the resulting JSON should be formatted</param>
43+
/// <returns>JSON string representing the DynamoDB item</returns>
44+
private static string ToJson(Dictionary<string, AttributeValue> item, bool prettyPrint)
45+
{
46+
if (item == null || item.Count == 0)
47+
{
48+
return "{}";
49+
}
50+
51+
using var stream = new MemoryStream();
52+
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = prettyPrint});
53+
54+
WriteJson(writer, item);
55+
56+
writer.Flush();
57+
return Encoding.UTF8.GetString(stream.ToArray());
58+
}
59+
60+
/// <summary>
61+
/// Writes a single DynamoDB attribute as a json. May be called recursively for maps.
62+
/// </summary>
63+
/// <param name="writer">JSON writer</param>
64+
/// <param name="item">Dictionary representing a DynamoDB item, or a map within an item</param>
65+
private static void WriteJson(Utf8JsonWriter writer, Dictionary<string, AttributeValue> item)
66+
{
67+
writer.WriteStartObject();
68+
69+
foreach (var attribute in item)
70+
{
71+
writer.WritePropertyName(attribute.Key);
72+
WriteJsonValue(writer, attribute.Value);
73+
}
74+
75+
writer.WriteEndObject();
76+
}
77+
78+
/// <summary>
79+
/// Writes a single DynamoDB attribute value as a json value
80+
/// </summary>
81+
/// <param name="writer">JSON writer</param>
82+
/// <param name="attribute">DynamoDB attribute</param>
83+
private static void WriteJsonValue(Utf8JsonWriter writer, AttributeValue attribute)
84+
{
85+
if (attribute.S != null)
86+
{
87+
writer.WriteStringValue(attribute.S);
88+
}
89+
else if (attribute.N != null)
90+
{
91+
#if NETCOREAPP3_1 // WriteRawValue was added in .NET 6, but we need to write out Number values without quotes
92+
using var document = JsonDocument.Parse(attribute.N);
93+
document.WriteTo(writer);
94+
#else
95+
writer.WriteRawValue(attribute.N);
96+
#endif
97+
}
98+
else if (attribute.B != null)
99+
{
100+
writer.WriteBase64StringValue(attribute.B.ToArray());
101+
}
102+
else if (attribute.BOOL != null)
103+
{
104+
writer.WriteBooleanValue(attribute.BOOL.Value);
105+
}
106+
else if (attribute.NULL != null)
107+
{
108+
writer.WriteNullValue();
109+
}
110+
else if (attribute.M != null)
111+
{
112+
WriteJson(writer, attribute.M);
113+
}
114+
else if (attribute.L != null)
115+
{
116+
writer.WriteStartArray();
117+
foreach (var item in attribute.L)
118+
{
119+
WriteJsonValue(writer, item);
120+
}
121+
writer.WriteEndArray();
122+
}
123+
else if (attribute.SS != null)
124+
{
125+
writer.WriteStartArray();
126+
foreach (var item in attribute.SS)
127+
{
128+
writer.WriteStringValue(item);
129+
}
130+
writer.WriteEndArray();
131+
}
132+
else if (attribute.NS != null)
133+
{
134+
writer.WriteStartArray();
135+
foreach (var item in attribute.NS)
136+
{
137+
#if NETCOREAPP3_1 // WriteRawValue was added in .NET 6, but we need to write out Number values without quotes
138+
using var document = JsonDocument.Parse(item);
139+
document.WriteTo(writer);
140+
#else
141+
writer.WriteRawValue(item);
142+
#endif
143+
}
144+
writer.WriteEndArray();
145+
}
146+
else if (attribute.BS != null)
147+
{
148+
writer.WriteStartArray();
149+
foreach (var item in attribute.BS)
150+
{
151+
writer.WriteBase64StringValue(item.ToArray());
152+
}
153+
writer.WriteEndArray();
154+
}
155+
}
156+
}
157+
}

Libraries/test/EventsTests.NET6/EventsTests.NET6.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<PackageId>EventsTests31</PackageId>
66
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
77
<RootNamespace>EventsTests.NET6</RootNamespace>
8+
<LangVersion>latest</LangVersion>
89
</PropertyGroup>
910

1011

@@ -54,13 +55,14 @@
5455
</ItemGroup>
5556

5657
<ItemGroup>
58+
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.301.14" />
5759
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
5860
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
5961
<PrivateAssets>all</PrivateAssets>
6062
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
6163
</PackageReference>
6264
<PackageReference Include="xunit" Version="2.4.1" />
63-
<PackageReference Include="AWSSDK.Core" Version="3.7.10.9" />
65+
<PackageReference Include="AWSSDK.Core" Version="3.7.302.13" />
6466
</ItemGroup>
6567

6668
<ItemGroup>

Libraries/test/EventsTests.NETCore31/EventsTests.NETCore31.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
77
<RuntimeIdentifiers>win7-x64;win7-x86</RuntimeIdentifiers>
88
<RootNamespace>EventsTests31</RootNamespace>
9+
<LangVersion>latest</LangVersion>
910
</PropertyGroup>
1011

1112

@@ -54,10 +55,11 @@
5455
</ItemGroup>
5556

5657
<ItemGroup>
58+
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.301.14" />
5759
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
5860
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
5961
<PackageReference Include="xunit" Version="2.2.0" />
60-
<PackageReference Include="AWSSDK.Core" Version="3.7.10.9" />
62+
<PackageReference Include="AWSSDK.Core" Version="3.7.302.13" />
6163
</ItemGroup>
6264

6365
<ItemGroup>

0 commit comments

Comments
 (0)