Aws-lambda-dotnet: Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer menggunakan casing properti yang berbeda dari Amazon.Lambda.Serialization.Json.JsonSerializer

Dibuat pada 15 Apr 2020  ·  43Komentar  ·  Sumber: aws/aws-lambda-dotnet

Tampaknya perilaku casing default telah berubah antara Amazon.Lambda.Serialization.Json.JsonSerializer dan Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer .

Berikut beberapa contoh kode untuk menguji perbedaannya:

// create an instance to serialize
var record = new Record {
    Foo = "Hello world!"
};

// show serialization with original Lambda serializer based on Newtonsoft.Json
var oldSerializer = SerializeWith(record, new Amazon.Lambda.Serialization.Json.JsonSerializer());
Console.WriteLine($"Amazon.Lambda.Serialization.Json.JsonSerializer: {oldSerializer}");

// show serialization with new Lambda serializer based on System.Text.Json
var newSerializer = SerializeWith(record, new Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer());
Console.WriteLine($"Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer: {newSerializer}");

// show serialization with System.Json.Text
var jsonTextSerializer = System.Text.Json.JsonSerializer.Serialize<Record>(record);
Console.WriteLine($"System.Text.Json.JsonSerializer: {jsonTextSerializer}");

// local functions
string SerializeWith<T>(T value, Amazon.Lambda.Core.ILambdaSerializer serializer) {
    using var buffer = new MemoryStream();
    serializer.Serialize<T>(value, buffer);;
    return System.Text.Encoding.UTF8.GetString(buffer.ToArray());
}

Kode di atas menghasilkan keluaran sebagai berikut:

Amazon.Lambda.Serialization.Json.JsonSerializer: {"Foo":"Hello world!"}
Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer: {"foo":"Hello world!"}
System.Text.Json.JsonSerializer: {"Foo":"Hello world!"}
bug

Komentar yang paling membantu

Apakah mungkin untuk mempertahankan topik ini?

Semua 43 komentar

Setuju saya seharusnya tidak mengganti casing antara 2 perpustakaan. Saya pikir kami kekurangan tes untuk permintaan dan respons khusus karena tes sekarang sebagian besar berfokus pada acara AWS.

Sekarang ini telah dikirim, mengubah perilaku default benar-benar tidak dapat dilakukan. Saran saya adalah menambahkan konstruktor baru yang memasukkan enum untuk gaya casing sehingga Anda dapat menyatakan casing yang ingin Anda gunakan. Saya kemudian dapat memperbarui template untuk menggunakan konstruktor baru. Bagaimana perasaan Anda tentang pekerjaan itu?

Saya tidak tahu apa ide di sini. Saya mengerti bahwa Anda tidak ingin merusak orang yang mungkin telah mengambil ketergantungan. Tampaknya kesalahan adalah percaya bahwa AWS memiliki konsistensi dalam penamaan bidang JSON (yaitu AWSNamingPolicy ). Itu tidak. Beberapa layanan menggunakan Pascal-casing, seperti CloudFormation:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html

Mengubah casing secara otomatis dan tidak menghormati perilaku default System.Text.Json adalah kesalahan fatal, IMHO. Mungkin pertimbangkan untuk merilis Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializerV2 dan meletakkan yang lama di atas es.

Untuk memperjelas, karena saya tidak terbiasa dengan cara kerjanya, deklarasi atribut assembly hanya digunakan untuk deserialisasi, benar?

[assembly: LambdaSerializer(typeof(Amazon.Lambda.SystemTextJson.LambdaJsonSerializer))]

Namun, apakah itu diperlukan jika saya menggunakan tanda tangan penangan ini?

Task<Stream> FunctionHandlerAsync(Stream stream, ILambdaContext context)

Apa yang terjadi jika tidak ada deklarasi LambdaSerializerAttribute untuk metode assembly atau entry-point?

@normj opsi mungkin untuk menambahkan atribut untuk secara eksplisit menamai properti json dan oleh karena itu menghormati penamaan terlepas dari kapitalisasi

Saya setuju dengan saran itu - menambahkannya hanya satu kali membosankan, tetapi selalu benar.

@normj IMHO ini adalah masalah implementasi yang perlu / harus ditangani dalam jangka panjang sebagai BUG karena ini adalah PERUBAHAN BREAKING yang tidak disengaja

@ 3GDXC Saya setuju ini adalah bug implementasi. Hanya memikirkan solusinya. Saat ini dalam paket kami memiliki satu serializer bernama LambdaJsonSerializer . Bagaimana jika kita menambahkan PascalCaseLambdaJsonSerializer dan CamelCaseLambdaJsonSerializer serializer yang diperpanjang dari LambdaJsonSerializer . Saya bisa mengubah template untuk menggunakan PascalCaseLambdaJsonSerializer untuk menjaga perilaku yang ada. Ini semacam versi yang lebih eksplisit dari saran @bjorg untuk memiliki LambdaJsonSerializerV2.

@normj IMHO akan lebih baik dan menghindari kebingungan untuk menambahkan atribut JsonPropertyName ke pesan sehingga terlepas dari konfigurasi / opsi serializer, Json yang dihasilkan mengikuti penamaan atribut.

Saya memahami sepenuhnya mengapa Anda enggan untuk memperkenalkan perubahan lebih lanjut (dengan koreksi) dalam hitungan hari sejak rilis dukungan .NET 3.1; dan jika kami (royal we) memiliki sejumlah masalah UP-FOR-GRABS, tidak ada pengujian unit / regresi yang dapat dibantu oleh komunitas untuk membuat implementasi berkembang dan menguji sebelum rilis.

Senang membantu jika / ketika diperlukan ucapkan saja.

Kerja bagus sejauh ini, senang melihat aws lamba dan dukungan inti .net tumbuh

@ 3GDXC Perlu diingat bahwa casing hanya mempengaruhi objek yang dikembalikan di mana kita harus beralih dari objek .NET ke string JSON. Dalam beberapa objek respons yang kami jual, saya menggunakan JsonPropertyName, berikut ini contohnya: https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.APIGatewayEvents/APIGatewayProxyResponse. cs # L18

Masalahnya adalah untuk objek respons yang dibuat orang lain di mana saya tidak mengontrol apakah mereka menggunakan atribut JsonPropertyName atau tidak.

@j poin yang bagus; Mungkin penasihat juga harus menyertakan SELALU menggunakan atribut JsonPropertyName untuk menerapkan penamaan eksplisit properti Anda dan / atau kontrak data (praktik terbaik)

@normj alternatif mungkin untuk mengabstraksi JsonSerializerOptions ke kelas LambdaSerializerOptions dan menambahkan opsi sebagai parameter konstruktor di atribut sehingga serializer dapat memiliki opsi kustom yang dapat diganti oleh pengembang pada tingkat perakitan / metode

Bagaimana dengan menandainya sebagai regresi dan memperbaikinya sebagai perubahan yang dapat merusak sekarang alih-alih menyebarkan lebih banyak kerugian? Saya menyebutnya _harm_ karena LambdaJsonSerializer , yang didasarkan pada System.Text.Json , tidak menghormati perilaku default tentang cara membuat serial properti. Tentu saja menggunakan [JsonPropertyName] memperbaikinya, tetapi meminta setiap orang untuk melakukan sesuatu untuk melawan perilaku yang tidak diinginkan tampaknya terlalu berat.

Berapa banyak orang yang akan terus menjumpai momen ini sebagai _?!?!? _ Saat mereka mengadopsi LambdaJsonSerializer sebagai penyambung standar mereka?

Halo, saya mengalami masalah ini di Fungsi Langkah setelah mengalihkan Tugas lambda ke .Net 3.1 + serializer baru. Ini mendatangkan malapetaka karena keluaran sekarang ada dalam camelcase sehingga bentuk mesin status berikutnya mencoba mengevaluasi JSON baru menggunakan Amazon States Language dan melontarkan pengecualian Fungsi Langkah.

Ada solusi rumit untuk saat ini. Dengan menyetel LAMBDA_NET_SERIALIZER_DEBUG=true dalam variabel lingkungan, _.options tidak pernah disetel dalam serializer yang menyebabkan kasing dikembalikan tanpa tersentuh. Saya tidak yakin apakah itu akan mengakibatkan dampak lain selain JSON tambahan yang dipancarkan ke Cloudwatch Logs.
https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Serialization.SystemTextJson/LambdaJsonSerializer.cs#L69 -L90

IMO, akan sangat merepotkan untuk mendekorasi semua model kami dengan dekorasi [JsonPropertyName] karena model kami terkubur di sejumlah perpustakaan nuget. Idealnya saya ingin perilaku default kembali ke PascalCasing asli seperti sebelumnya tetapi saya baik-baik saja dengan menggunakan PascalCaseLambdaJsonSerializer eksplisit dengan lambda ketika dipanggil dalam proyek Fungsi Langkah kami.

Terima kasih!

Saya cukup yakin bahwa solusi kludgy adalah bug.

Poin bagus pada struktur data yang ditentukan oleh majelis hulu.

Saya tidak tahu apa efek sampingnya pada hal-hal lain tanpa atribut [JsonPropertyName] , tetapi menggunakan konstruktor LambdaJsonSerializer yang memungkinkan Anda untuk menyesuaikan serializer JSON dapat dikembalikan ke perilaku PascalCase default dengan pengaturan JsonSerializerOptions.PropertyNamingPolicy menjadi null .

Menautkan ke masalah # 628 karena terkait dengan diskusi ini.

Saya pikir ini terkait.

Melihat APIGatewayProxyRequest.cs , saya melihat tidak ada penjelasan [JsonPropertyName] . Satu-satunya alasan ini berhasil adalah karena a) LambdaJsonSerializer default untuk deserialization tidak sensitif huruf dan b) LambdaJsonSerializer menggunakan camel-casing pada serialisasi.

Saya dapat melihat bagaimana ini menghemat banyak waktu untuk membuat anotasi semua kelas permintaan / tanggapan di berbagai majelis pembantu, tetapi itu berarti bahwa ketika kita menggunakan rakitan pembantu, kita harus menggunakan LambdaJsonSerializer dalam fungsi kita.

Kalau dipikir-pikir, bukankah lebih masuk akal untuk meletakkan anotasi [LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] pada kelas POCO yang digunakan oleh penangan fungsi daripada kelas fungsi itu sendiri? Tampaknya, pada akhirnya, fungsi tersebut harus menggunakan serializer yang cocok dengan kelas permintaan / respons.

@bjorg IMO POCO adalah tempat yang salah untuk memiliki atribut metadata tentang serialisasi yang akan digunakan; POCO seharusnya hanya peduli dengan domainnya yaitu atribut validasi model dan tipe / penamaan properti; serialisasi harus menghormati / menggunakan anotasi model ini.

IMHO atribut LambdaSerializer harus diubah untuk menerima jenis serialisasi misalnya. Amazon.Lambda.Serialization.Json.JsonSerializer dengan opsi serialisasi opsional; jika opsi tidak diberikan, pengaturan default & kompatibel akan digunakan.

Tetapi POCO perlu dianotasi dengan atribut serializer yang benar: [JsonProperty] untuk Newtonsoft dan [JsonPropertyName] untuk System.Text.Json. Akibatnya, POCO terikat ke serializer.

Sepertinya [DataMember] akan didukung oleh Newtonsoft.Json dan System.Text.Json . Namun, tidak sampai .NET 5 untuk yang terakhir. :(
https://github.com/dotnet/runtime/issues/29975

Sementara itu, solusinya adalah memberi anotasi pada semua POCO dengan [DataMember] dan [JsonPropertyName] . Kedua atribut ditentukan dalam .NET Core 3.1 dan oleh karena itu tidak memerlukan dependensi eksternal tambahan.

Bukankah ini memastikan serialisasi / deserialization yang konsisten untuk semua kelas, setidaknya untuk nama properti? Pengonversi harus didaftarkan dengan implementasi ILambdaSerialize .

Masalah terkait di sana ditutup. Pemahaman saya dari membaca sekilas utas itu adalah mereka tidak berniat untuk mendukungnya: https://github.com/dotnet/runtime/issues/29975#issuecomment -609985802

Ya. Saya salah membaca. Saya melihat tautan 5.0 dan melompat ke kesimpulan yang salah.

Saya menerbitkan PR https://github.com/aws/aws-lambda-dotnet/pull/636 untuk mengatasi masalah ini. Saya akan menghargai umpan balik atau lebih baik lagi mengunduh pratinjau build dari tautan di PR dan membantu memverifikasi perubahan itu berfungsi untuk Anda.

Pertama, terima kasih sudah menangani ini begitu cepat. Maaf itu merusak hari Sabtu Anda.

Sekilas terlihat bagus. Saat ini saya sedang dalam proses untuk merobek semua referensi Newtonsoft.Json dan sayangnya saya tidak dalam keadaan di mana saya dapat memverifikasi perbaikannya. Untuk saat ini, saya hanya menyalin kelas serializer yang bermasalah dan menghapus pernyataan yang menyinggung. Mudah-mudahan besok EOD, saya bisa menguji perubahan ini di cabang dev saya.

Hal pertama yang terlintas dalam pikiran adalah kemungkinan anotasi yang hilang. Apakah ada struktur data respons yang tidak menggunakan [DataMember] dan sebaliknya mengandalkan kerangka unta implisit?

@bjorg Jangan khawatir. Setelah pertemuan seminggu, menulis dokumen dan membantu anak-anak bersekolah, sangat menyenangkan memiliki saat-saat tenang dan melakukan pengkodean hari Sabtu.

Kami memiliki potensi kehilangan penjelasan [DataMember] dengan serializer Newtonsoft. Saya tidak terlalu khawatir tentang itu karena untuk tipe yang diketahui kami memiliki tes untuk itu. Dalam hal ini celah saya melewatkan tes pada respons khusus.

Apakah mungkin untuk merilis -rc1 ? Alternatifnya, AFAIK, bagi saya jika tidak meretas file _.csproj_ saya dengan konstanta kompilasi yang benar diaktifkan. Apakah ada cara lain?

@bjorg Di PR ada link ke file zip yang berisi paket NuGet prebuilt, dapatkah Anda mensetup sumber NuGet lokal dan meletakkan paket di sana?

Mempelajari sesuatu yang baru hari ini: cara mendapatkan umpan lokal. Ternyata sangat mudah di .NET Core (lihat artikel SO ).

Umpan balik saya yang paling relevan adalah mengekspos _options sebagai properti Options dilindungi / publik sehingga kelas turunan dapat menggunakannya juga.

Jika tidak, semuanya hebat dengan kode baru ini dari sisi saya. Terima kasih!

@normj beri tahu saya jika / jika ada paket nuget yang diperbarui. Senang bisa mencobanya lagi.

https://github.com/aws/aws-lambda-dotnet/issues/544#issuecomment -567780775

^ Apakah karena tidak menggunakan casing unta merusak API Gateway?

Cos Pascal berfungsi dengan baik jika lambda ada di ALB, tetapi tidak berfungsi di API Gateway, inkonsistensi ini membingungkan. Bagaimana cara kerjanya sebelum pindah ke system.text?

Ini adalah perubahan besar; Antarmuka tidak sesuai. Karena kurangnya pengujian integrasi dan / atau tinjauan komunitas kandidat rilis, pelanggaran prinsip pemisahan antarmuka ini telah lolos. Semakin lama hal ini dibiarkan tidak terselesaikan, semakin besar biaya dan waktu kerja terbuang yang akan ditimbulkan bagi klien AWS, yang mengakibatkan dampak reputasi bagi AWS.

Saya sarankan Anda pindah untuk menandai rilis ini sebagai rusak dan mencegah migrasi ke 3.1 untuk semua pengembang sampai perbaikan disepakati.
Selain itu, saya juga merekomendasikan agar perbaikan apa pun didiskusikan dan diuji sepenuhnya oleh komunitas untuk mengurangi kemungkinan memperburuk masalah.

@lukebrowell Pekerjaan untuk pembuat serial telah dilakukan di depan umum dengan PR dikirimkan kembali pada bulan Januari. https://github.com/aws/aws-lambda-dotnet/pull/568 PR melampirkan paket prebuilt untuk pengujian yang dapat dilakukan dengan runtime Lambda kustom.

Kami membahas perbaikan di sini bersama dengan PR dan saya menyambut umpan balik tentang perbaikan yang diusulkan https://github.com/aws/aws-lambda-dotnet/pull/636

Saya setuju ini adalah perubahan besar dan saya kecewa hal itu terjadi, tetapi saya tidak setuju dengan tingkat keparahan yang Anda sarankan. Masalah ini hanya memengaruhi fungsi Lambda yang mengembalikan respons khusus, tidak semua fungsi Lambda dan Amazon.Lambda.Serialization.Json yang ada berfungsi sama, jadi saya tidak percaya adil untuk mengatakan bahwa seluruh rilis 3.1 Lambda rusak. Tapi sekali lagi saya mengerti frustrasinya dan saya minta maaf bug ini lewat.

Saya berharap untuk mendorong perubahan dalam PR awal minggu depan kecuali ada umpan balik yang signifikan tentang perubahan yang menyebabkan penundaan rilis.

@bjorg PR telah dimutakhirkan dengan tautan ke pratinjau2 paket prebuilt. https://normj-packages.s3.us-west-2.amazonaws.com/rework-serialization-preview2.zip

@normj Saya menyadari komunitas sebagian bertanggung jawab di sini sehubungan dengan melewatkan masalah ini karena (kami) memberikan tekanan untuk merilis / mendukung runtime .netcore 3.1 sebagai gambar lambda resmi dan tidak melaporkan ini atau memberikan umpan balik. IMHO sementara saya memahami pandangan Anda sehubungan dengan komentar @lukebrowell Saya setuju sebagian dengan @lukebrowell dan menyarankan agar unit kerja dimulai (dengan keterlibatan komunitas penuh) untuk membuka diskusi seputar fitur / desain perpustakaan fungsi / layanan aspnetcore lambda dengan maksud untuk mengatasi segala kekurangan dan / atau bug yang telah diidentifikasi dengan cara yang membantu pengembangan bergerak maju, karena paket ini terasa sedikit dari pekerjaan TBH yang terburu-buru.

Saya ingin melihat komunitas yang lebih kuat. Saya telah nongkrong di awsdevelopers.slack.com, tetapi saluran #dotnet agak sepi. Apakah ada tempat lain di mana orang-orang Lambda .NET Core berkumpul?

@bjorg Saya akan bergabung;) sampai jumpa di sana (secara virtual)

@bjorg mungkin mendapatkan undangan?

Mendapatkan link undangan dari moderator. Akan diposting di sini.

Apakah mungkin untuk mempertahankan topik ini?

Setuju, mari kita pertahankan topik ini. Saya membuat masalah komunitas # 647 tentang cara menghubungi saya untuk menambahkan Anda ke grup kendur AWS.

Ya, saya menerima saran tentang cara mengatur komunikasi komunitas dengan lebih baik dan di mana saya dapat melakukan lebih baik tentang komunikasi saya sendiri dan bagaimana saya dapat lebih terlibat.

_preview2_ terlihat bagus untuk saya.

Versi 2.0.0 dari Amazon.Lambda.Serialization.SystemTextJson keluar dengan perubahan. Ambil utama itu perbarui kelas serializer menjadi DefaultLambdaJsonSerializer .

Saya juga menerbitkan entri blog yang memiliki bagian yang menjelaskan perubahan tersebut.
https://aws.amazon.com/blogs/developer/one-month-update-to-net-core-3-1-lambda/

Apakah halaman ini membantu?
0 / 5 - 0 peringkat