From 045150964bbdd7fde8ffa77863a0766990c62186 Mon Sep 17 00:00:00 2001 From: Simon Hartcher Date: Wed, 4 Jun 2025 15:56:02 +1000 Subject: [PATCH] fix: handle structures with no members --- codegen/src/main.zig | 27 ++++++++++++++++++++++++--- src/aws.zig | 29 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/codegen/src/main.zig b/codegen/src/main.zig index 52e7112..2ca13db 100644 --- a/codegen/src/main.zig +++ b/codegen/src/main.zig @@ -977,7 +977,7 @@ const WriteMemberJsonParams = struct { member: smithy.TypeMember, }; -fn writeStructureMemberJson(params: WriteMemberJsonParams, writer: std.io.AnyWriter) !void { +fn writeStructureJson(params: WriteMemberJsonParams, writer: std.io.AnyWriter) !void { const shape_type = "structure"; const allocator = params.state.allocator; const state = params.state; @@ -988,16 +988,33 @@ fn writeStructureMemberJson(params: WriteMemberJsonParams, writer: std.io.AnyWri const structure_name = try std.fmt.allocPrint(params.state.allocator, "{s}_{s}_{d}", .{ params.field_name, shape_type, state.indent_level }); defer params.state.allocator.free(structure_name); + const object_value_capture = try std.fmt.allocPrint(allocator, "{s}_capture", .{structure_name}); + defer allocator.free(object_value_capture); + try writer.print("\n// start {s}: {s}\n", .{ shape_type, structure_name }); defer writer.print("// end {s}: {s}\n", .{ shape_type, structure_name }) catch std.debug.panic("Unreachable", .{}); if (try getJsonMembers(allocator, shape, state)) |json_members| { if (json_members.items.len > 0) { + const is_optional = shapeIsOptional(params.member.traits); + + var object_value = params.field_value; + + if (is_optional) { + object_value = object_value_capture; + + try writer.print("if ({s}) |{s}|", .{ params.field_value, object_value_capture }); + try writer.writeAll("{\n"); + } + try writer.writeAll("try jw.beginObject();\n"); try writer.writeAll("{\n"); + try writer.print("const unused_capture_{s} = {s};\n", .{ structure_name, object_value }); + try writer.print("_ = unused_capture_{s};\n", .{structure_name}); + for (json_members.items) |member| { - const member_value = try getMemberValueJson(allocator, params.field_value, member); + const member_value = try getMemberValueJson(allocator, object_value, member); defer allocator.free(member_value); try writer.print("try jw.objectField(\"{s}\");\n", .{member.json_key}); @@ -1015,6 +1032,10 @@ fn writeStructureMemberJson(params: WriteMemberJsonParams, writer: std.io.AnyWri try writer.writeAll("}\n"); try writer.writeAll("try jw.endObject();\n"); + + if (is_optional) { + try writer.writeAll("}\n"); + } } } } @@ -1167,7 +1188,7 @@ fn writeMemberJson(params: WriteMemberJsonParams, writer: std.io.AnyWriter) anye defer state.popFromTypeStack(); switch (shape) { - .structure, .uniontype => try writeStructureMemberJson(params, writer), + .structure, .uniontype => try writeStructureJson(params, writer), .list => |l| try writeListJson(l, params, writer), .map => |m| try writeMapJson(m, params, writer), .timestamp => try writeScalarJson("timestamp", params, writer), diff --git a/src/aws.zig b/src/aws.zig index 4c80f94..c4ddb3d 100644 --- a/src/aws.zig +++ b/src/aws.zig @@ -2701,3 +2701,32 @@ test "jsonStringify" { try testing.expectEqualStrings("1234", json_parsed.value.arn); try testing.expectEqualStrings("bar", json_parsed.value.tags.foo); } + +test "jsonStringify nullable object" { + const request = services.lambda.CreateAliasRequest{ + .function_name = "foo", + .function_version = "bar", + .name = "baz", + .routing_config = services.lambda.AliasRoutingConfiguration{ + .additional_version_weights = null, + }, + }; + + const request_json = try std.json.stringifyAlloc(std.testing.allocator, request, .{}); + defer std.testing.allocator.free(request_json); + + const json_parsed = try std.json.parseFromSlice(struct { + FunctionName: []const u8, + FunctionVersion: []const u8, + Name: []const u8, + RoutingConfig: struct { + AdditionalVersionWeights: ?struct {}, + }, + }, testing.allocator, request_json, .{ .ignore_unknown_fields = true }); + defer json_parsed.deinit(); + + try testing.expectEqualStrings("foo", json_parsed.value.FunctionName); + try testing.expectEqualStrings("bar", json_parsed.value.FunctionVersion); + try testing.expectEqualStrings("baz", json_parsed.value.Name); + try testing.expectEqual(null, json_parsed.value.RoutingConfig.AdditionalVersionWeights); +}