Skip to content

Commit

Permalink
Implemented custom DictionaryLongToStringJsonConverter (System.Text.J…
Browse files Browse the repository at this point in the history
…son.Serialization.JsonConverter) for non-NetStandard 2.0 target(s) for handling Kinesis and DynamoDB TimeWindowEvent State property.
  • Loading branch information
ashishdhingra committed Aug 23, 2023
1 parent 5498aa3 commit 8726a45
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.3.24" />
</ItemGroup>

<ItemGroup>
<Compile Remove="Converters\DictionaryLongToStringJsonConverter.cs" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard2.0' ">
<Compile Include="Converters\DictionaryLongToStringJsonConverter.cs" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Amazon.Lambda.DynamoDBEvents.Converters
{
public class DictionaryLongToStringJsonConverter : JsonConverter<Dictionary<string, string>>
{
public override Dictionary<string, string> Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException($"JsonTokenType was of type {reader.TokenType}, only objects are supported.");
}

var dictionary = new Dictionary<string, string>();

while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return dictionary;
}

// Get the key.
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException("JsonTokenType was not PropertyName.");
}

var propertyName = reader.GetString();

if (string.IsNullOrWhiteSpace(propertyName))
{
throw new JsonException("Failed to get property name.");
}

// Get the value.
reader.Read();
var keyValue = ExtractValue(ref reader, options);
dictionary.Add(propertyName, keyValue);
}

return dictionary;
}

public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)
{
// Use the built-in serializer, because it can handle dictionaries with string keys.
JsonSerializer.Serialize(writer, value, options);
}

private string ExtractValue(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.Number:
if (reader.TryGetInt64(out var result))
{
return result.ToString();
}
throw new JsonException($"Unable to convert '{reader.TokenType}' to long value.");
case JsonTokenType.String: // If it is string, then use as it is.
return reader.GetString();
default:
throw new JsonException($"'{reader.TokenType}' is not supported.");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ namespace Amazon.Lambda.DynamoDBEvents
using System;
using System.Collections.Generic;

#if !NETSTANDARD2_0
using Amazon.Lambda.DynamoDBEvents.Converters;
using System.Text.Json.Serialization;
#endif

/// <summary>
/// Represents an Amazon DynamodDB event when using time windows.
/// https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html#services-ddb-windows
Expand All @@ -17,6 +22,9 @@ public class DynamoDBTimeWindowEvent : DynamoDBEvent
/// <summary>
/// State being built up to this invoke in the time window.
/// </summary>
#if !NETSTANDARD2_0
[JsonConverter(typeof(DictionaryLongToStringJsonConverter))]
#endif
public Dictionary<string, string> State { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
using System.Collections.Generic;
using System.Runtime.Serialization;

#if !NETSTANDARD2_0
using Amazon.Lambda.DynamoDBEvents.Converters;
using System.Text.Json.Serialization;
#endif

/// <summary>
/// Response type to return a new state for the time window and to report batch item failures.
/// </summary>
Expand All @@ -16,6 +21,9 @@ public class DynamoDBTimeWindowResponse
[DataMember(Name = "state")]
#if NETCOREAPP_3_1
[System.Text.Json.Serialization.JsonPropertyName("state")]
#endif
#if !NETSTANDARD2_0
[JsonConverter(typeof(DictionaryLongToStringJsonConverter))]
#endif
public Dictionary<String, String> State { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@
<PackageReference Include="AWSSDK.Kinesis" Version="3.7.0" />
</ItemGroup>

<ItemGroup>
<Compile Remove="Converters\DictionaryLongToStringJsonConverter.cs" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard2.0' ">
<Compile Include="Converters\DictionaryLongToStringJsonConverter.cs" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Amazon.Lambda.KinesisEvents.Converters
{
public class DictionaryLongToStringJsonConverter : JsonConverter<Dictionary<string, string>>
{
public override Dictionary<string, string> Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException($"JsonTokenType was of type {reader.TokenType}, only objects are supported.");
}

var dictionary = new Dictionary<string, string>();

while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return dictionary;
}

// Get the key.
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException("JsonTokenType was not PropertyName.");
}

var propertyName = reader.GetString();

if (string.IsNullOrWhiteSpace(propertyName))
{
throw new JsonException("Failed to get property name.");
}

// Get the value.
reader.Read();
var keyValue = ExtractValue(ref reader, options);
dictionary.Add(propertyName, keyValue);
}

return dictionary;
}

public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)
{
// Use the built-in serializer, because it can handle dictionaries with string keys.
JsonSerializer.Serialize(writer, value, options);
}

private string ExtractValue(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.Number:
if (reader.TryGetInt64(out var result))
{
return result.ToString();
}
throw new JsonException($"Unable to convert '{reader.TokenType}' to long value.");
case JsonTokenType.String: // If it is string, then use as it is.
return reader.GetString();
default:
throw new JsonException($"'{reader.TokenType}' is not supported.");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ namespace Amazon.Lambda.KinesisEvents
using System;
using System.Collections.Generic;

#if !NETSTANDARD2_0
using Amazon.Lambda.KinesisEvents.Converters;
using System.Text.Json.Serialization;
#endif

/// <summary>
/// Represents an Amazon Kinesis event when using time windows.
/// https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-windows
Expand All @@ -17,6 +22,9 @@ public class KinesisTimeWindowEvent : KinesisEvent
/// <summary>
/// State being built up to this invoke in the time window.
/// </summary>
#if !NETSTANDARD2_0
[JsonConverter(typeof(DictionaryLongToStringJsonConverter))]
#endif
public Dictionary<string, string> State { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
using System.Collections.Generic;
using System.Runtime.Serialization;

#if !NETSTANDARD2_0
using Amazon.Lambda.KinesisEvents.Converters;
using System.Text.Json.Serialization;
#endif

/// <summary>
/// Response type to return a new state for the time window and to report batch item failures.
/// </summary>
Expand All @@ -16,6 +21,9 @@ public class KinesisTimeWindowResponse
[DataMember(Name = "state")]
#if NETCOREAPP_3_1
[System.Text.Json.Serialization.JsonPropertyName("state")]
#endif
#if !NETSTANDARD2_0
[JsonConverter(typeof(DictionaryLongToStringJsonConverter))]
#endif
public Dictionary<String, String> State { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,7 @@ protected virtual JsonSerializerOptions CreateDefaultJsonSerializationOptions()
new DateTimeConverter(),
new MemoryStreamConverter(),
new ConstantClassConverter(),
new ByteArrayConverter(),
new LongToStringJsonConverter()
new ByteArrayConverter()
}
};

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public LambdaJsonSerializer()
_options.Converters.Add(new MemoryStreamConverter());
_options.Converters.Add(new ConstantClassConverter());
_options.Converters.Add(new ByteArrayConverter());
_options.Converters.Add(new LongToStringJsonConverter());

WriterOptions = new JsonWriterOptions()
{
Expand Down

0 comments on commit 8726a45

Please sign in to comment.