Передача словаря в AWS Lambda сериализует его в словарь

#c# #aws-lambda #system.text.json

Вопрос:

Моя пошаговая функция AWS передает пользовательский объект из Лямбда в Лямбда. Одним из свойств этого объекта является Dictionary<string, object> … но сериализатор AWS JSON превращается во что-то вроде Dictionary<string, JsonElement> . Поэтому, если я передам ему объект, который Newtonsoft десериализует следующим образом:

 { "name": "Tom", "age": 99, "married": true }
 

…то, что Лямбда получает в качестве входного параметра, выглядит так:

 {
    "name" : { "ValueKind": 3 }, 
    "age"  : { "ValueKind": 2 },
    "married" : {"ValueKind: 1 }
}
 

(Игнорируйте мои ценности, они не важны.)

Это означает, что входные данные для моей Лямбды непригодны для использования.

Я не хочу писать и поддерживать кучу кода переводчика, чтобы отмечать каждую запись в словаре и восстанавливать ее для всех 10 Лямбд в моей пошаговой функции. (Я все равно не уверен, что смогу. Я предполагаю, что при такой десериализации исходное значение теряется.)

Предложения? Могу ли я поменять сериализатор Amazon JSON на сериализатор Newtonsoft? Могу ли я создать расширение, которое поможет мне?

Ответ №1:

Могу ли я поменять сериализатор Amazon JSON на сериализатор Newtonsoft?

Похоже, что вы можете — посмотрите документацию AWS:

Если входные и выходные параметры вашей функции не относятся к типу System.IO.Stream, вам потребуется их сериализовать. AWS Lambda предоставляет сериализатор по умолчанию, который может быть применен на уровне сборки или метода вашего приложения, или вы можете определить свой собственный, реализовав интерфейс ILambdaSerializer, предоставляемый Amazon.Лямбда.Основная библиотека. Дополнительные сведения см. в разделе Развертывание лямбда-функций C# с архивами zip-файлов.

Чтобы добавить атрибут сериализатора по умолчанию в метод, сначала добавьте зависимость от Amazon.Лямбда.Сериализация.Json в вашем файле .csproj.

 <Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AssemblyName>AssemblyName</AssemblyName>
    </PropertyGroup>
      
    <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="1.2.0" />
    <PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.3.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.8.0" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
    </ItemGroup>
</Project>
 

Они также включают пример того, как указывать, какой метод использует какой сериализатор:

 public class ProductService{
    [LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
    public Product DescribeProduct(DescribeProductRequest request)
    {
      return catalogService.DescribeProduct(request.Id);
    }
   
   [LambdaSerializer(typeof(MyJsonSerializer))]
   public Customer DescribeCustomer(DescribeCustomerRequest request)
   {
      return customerService.DescribeCustomer(request.Id);
   }
}
 

Они также рекомендуют для проектов .NET Core 3.1 (и, предположительно, выше) использовать их сериализатор, который используется System.Text.Json для минимизации производительности холодного запуска:

Если вы ориентируетесь на .NET Core 3.1, этот сериализатор настоятельно рекомендуется использовать в Amazon.Лямбда.Сериализация.Json и может значительно снизить производительность холодного запуска в Lambda.

Комментарии:

1. Большое спасибо! Я подумал, что есть способ, но отступил. Беспокоился, что потрачу целый день на поиски этого и обнаружу, что у него дюжина странных побочных эффектов.

Ответ №2:

Лучший ответ, который я нашел, был дан Джозефом Оттоссоном.

Я попытался создать свой собственный словарь, который опрашивал бы каждую новую пару Ключ/значение и помещал каждую запись во внутренний словарь только для строк или словарь только для длинных строк, поэтому избегайте хранения каких-либо данных как object . Но ничего не помогало.

К моей радости, статья попадает в тупик в моем проблемном пространстве: как де/сериализовать объекты со Dictionary<string, object> свойствами. Он создал JsonConverterAttribute то, что делает свое дело.