Skip to content

Commit 94b742b

Browse files
committed
codegen: Add support for REST-XML Union responses
Adds support for deserializing REST-XML union resources Fixes aws#939 Related to smithy-lang/smithy#678
1 parent 15e052d commit 94b742b

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/JsonShapeDeserVisitor.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,6 @@ protected void deserializeUnion(GenerationContext context, UnionShape shape) {
244244
symbol.getNamespace()
245245
).build();
246246
writer.write("uv = &$T{Tag: key}", unknownMemberSymbol);
247-
writer.writeDocs("TODO: FIX ME");
248-
writer.write("_ = value");
249247
writer.write("break loop");
250248
});
251249
});

codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/XmlShapeDeserVisitor.java

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import software.amazon.smithy.go.codegen.CodegenUtils;
1313
import software.amazon.smithy.go.codegen.GoWriter;
1414
import software.amazon.smithy.go.codegen.SmithyGoDependency;
15+
import software.amazon.smithy.go.codegen.SymbolUtils;
16+
import software.amazon.smithy.go.codegen.UnionGenerator;
1517
import software.amazon.smithy.go.codegen.integration.DocumentShapeDeserVisitor;
1618
import software.amazon.smithy.go.codegen.integration.ProtocolGenerator;
1719
import software.amazon.smithy.go.codegen.integration.ProtocolGenerator.GenerationContext;
@@ -403,10 +405,64 @@ protected void deserializeDocument(GenerationContext context, DocumentShape shap
403405
@Override
404406
protected void deserializeUnion(GenerationContext context, UnionShape shape) {
405407
GoWriter writer = context.getWriter();
406-
// TODO: implement union deserialization
407-
// The tricky part is going to be accumulating bytes for unknown members.
408-
LOGGER.warning("Union type is currently unsupported for XML deserialization.");
409-
context.getWriter().writeDocs("TODO: implement union serialization.");
408+
SymbolProvider symbolProvider = context.getSymbolProvider();
409+
Symbol symbol = symbolProvider.toSymbol(shape);
410+
Model model = context.getModel();
411+
412+
writer.write("var uv $P", symbol);
413+
414+
// Iterate through the decoder. The member visitor will handle popping xml tokens
415+
// enclosed within a xml start and end element.
416+
// TODO [xmlUnion] need to consume closing token
417+
writer.openBlock("loop: for {", "}", () -> {
418+
writer.write("t, done, err := decoder.Token()");
419+
writer.write("if err != nil { return err }");
420+
writer.write("if done { break }");
421+
422+
// Create a new decoder for each member
423+
writer.write("originalDecoder := decoder");
424+
writer.write("decoder = smithyxml.WrapNodeDecoder(originalDecoder.Decoder, t)");
425+
writer.insertTrailingNewline();
426+
427+
writer.openBlock("switch {", "}", () -> {
428+
Set<MemberShape> members = new TreeSet<>(shape.members());
429+
for (MemberShape member : members) {
430+
// check if member is not a document binding or has a xmlAttribute trait
431+
if (!memberFilter.test(member) || member.hasTrait(XmlAttributeTrait.ID)) {
432+
continue;
433+
}
434+
Symbol targetSymbol = symbolProvider.toSymbol(member);
435+
Symbol memberSymbol = SymbolUtils.createValueSymbolBuilder(
436+
symbolProvider.toMemberName(member),
437+
symbol.getNamespace()
438+
).build();
439+
440+
writer.addUseImports(SmithyGoDependency.STRINGS);
441+
442+
String serializedMemberName = getSerializedMemberName(member);
443+
writer.openBlock("case strings.EqualFold($S, t.Name.Local):", "", serializedMemberName, () -> {
444+
writer.write("var mv $P", targetSymbol);
445+
model.expectShape(member.getTarget()).accept(getMemberDeserVisitor(member, "mv", false));
446+
writer.write("uv = &$T{Value: mv}", memberSymbol);
447+
writer.write("break loop");
448+
});
449+
}
450+
451+
writer.openBlock("default:", "", () -> {
452+
// This is the function to take a value and convert it to the union type.
453+
Symbol unknownMemberSymbol = SymbolUtils.createValueSymbolBuilder(
454+
UnionGenerator.UNKNOWN_MEMBER_NAME,
455+
symbol.getNamespace()
456+
).build();
457+
writer.write("uv = &$T{Tag: t.Name.Local}", unknownMemberSymbol);
458+
writer.write("break loop");
459+
});
460+
});
461+
// re-assign the original decoder
462+
writer.write("decoder = originalDecoder");
463+
});
464+
465+
writer.write("*v = uv");
410466
writer.write("return nil");
411467
}
412468
}

0 commit comments

Comments
 (0)