fix json serialization for null/empty maps

This commit is contained in:
Emil Lerch 2025-03-21 09:59:33 -07:00
parent 34c097e45f
commit 9e8b3a6fc6
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 70 additions and 2 deletions

View file

@ -4,7 +4,7 @@ const std = @import("std");
pub fn serializeMap(map: anytype, key: []const u8, options: anytype, out_stream: anytype) !bool {
if (@typeInfo(@TypeOf(map)) == .optional) {
if (map == null)
return true
return false
else
return serializeMapInternal(map.?, key, options, out_stream);
}
@ -12,7 +12,23 @@ pub fn serializeMap(map: anytype, key: []const u8, options: anytype, out_stream:
}
fn serializeMapInternal(map: anytype, key: []const u8, options: anytype, out_stream: anytype) !bool {
if (map.len == 0) return true;
if (map.len == 0) {
var child_options = options;
if (child_options.whitespace) |*child_ws|
child_ws.indent_level += 1;
try out_stream.writeByte('"');
try out_stream.writeAll(key);
_ = try out_stream.write("\":");
if (options.whitespace) |ws| {
if (ws.separator) {
try out_stream.writeByte(' ');
}
}
try out_stream.writeByte('{');
try out_stream.writeByte('}');
return true;
}
// TODO: Map might be [][]struct{key, value} rather than []struct{key, value}
var child_options = options;
if (child_options.whitespace) |*child_ws|

View file

@ -1310,6 +1310,58 @@ test "custom serialization for map objects" {
, buffer.items);
}
test "proper serialization for kms" {
// Github issue #8
// https://github.com/elerch/aws-sdk-for-zig/issues/8
const allocator = std.testing.allocator;
var buffer = std.ArrayList(u8).init(allocator);
defer buffer.deinit();
const req = services.kms.encrypt.Request{
.encryption_algorithm = "SYMMETRIC_DEFAULT",
// Since encryption_context is not null, we expect "{}" to be the value
// here, not "[]", because this is our special AWS map pattern
.encryption_context = &.{},
.key_id = "42",
.plaintext = "foo",
.dry_run = false,
.grant_tokens = &[_][]const u8{},
};
try json.stringify(req, .{ .whitespace = .{} }, buffer.writer());
try std.testing.expectEqualStrings(
\\{
\\ "KeyId": "42",
\\ "Plaintext": "foo",
\\ "EncryptionContext": {},
\\ "GrantTokens": [],
\\ "EncryptionAlgorithm": "SYMMETRIC_DEFAULT",
\\ "DryRun": false
\\}
, buffer.items);
var buffer_null = std.ArrayList(u8).init(allocator);
defer buffer_null.deinit();
const req_null = services.kms.encrypt.Request{
.encryption_algorithm = "SYMMETRIC_DEFAULT",
// Since encryption_context here *IS* null, we expect simply "null" to be the value
.encryption_context = null,
.key_id = "42",
.plaintext = "foo",
.dry_run = false,
.grant_tokens = &[_][]const u8{},
};
try json.stringify(req_null, .{ .whitespace = .{} }, buffer_null.writer());
try std.testing.expectEqualStrings(
\\{
\\ "KeyId": "42",
\\ "Plaintext": "foo",
\\ "EncryptionContext": null,
\\ "GrantTokens": [],
\\ "EncryptionAlgorithm": "SYMMETRIC_DEFAULT",
\\ "DryRun": false
\\}
, buffer_null.items);
}
test "REST Json v1 builds proper queries" {
const allocator = std.testing.allocator;
const svs = Services(.{.lambda}){};