Unverified Commit 28af7e22 authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Implement JsonParserGenerator using smithy-json (#498)

* Implement JsonParserGenerator using smithy-json

* CR feedback

* Fix smithy-json test

* Simplify JsonParserGenerator

* Fix clippy warning
parent 206ef913
Loading
Loading
Loading
Loading
+76 −1
Original line number Diff line number Diff line
@@ -53,7 +53,16 @@ apply QueryPrecedence @httpRequestTests([
@restJson1
service RestJsonExtras {
    version: "2019-12-16",
    operations: [StringPayload, PrimitiveIntHeader, EnumQuery, StatusResponse, MapWithEnumKeyOp, PrimitiveIntOp]
    operations: [
        StringPayload,
        PrimitiveIntHeader,
        EnumQuery,
        StatusResponse,
        MapWithEnumKeyOp,
        PrimitiveIntOp,
        EscapedStringValues,
        NullInNonSparse,
    ]
}

@http(uri: "/StringPayload", method: "POST")
@@ -188,3 +197,69 @@ operation MapWithEnumKeyOp {
    input: MapWithEnumKeyInputOutput,
    output: MapWithEnumKeyInputOutput,
}


@enum([
    { value: "has\"quotes", name: "HAS_QUOTES" },
    { value: "normal", name: "NORMAL" },
])
string EnumWithEscapedChars

structure EscapedStringValuesInputOutput {
    enum: EnumWithEscapedChars,
    @jsonName("also\"has\"quotes")
    someString: String,
}

@http(uri: "/escaped-string-values", method: "POST")
@httpRequestTests([
    {
        id: "EscapedStringValuesRequest",
        uri: "/escaped-string-values",
        method: "POST",
        protocol: "aws.protocols#restJson1",
        body: "{\"enum\":\"has\\\"quotes\",\"also\\\"has\\\"quotes\":\"test\"}",
        params: { enum: "has\"quotes", someString: "test" },
    }
])
@httpResponseTests([
    {
        id: "EscapedStringValuesResponse",
        protocol: "aws.protocols#restJson1",
        code: 200,
        body: "{\"enum\":\"has\\\"quotes\",\"also\\\"has\\\"quotes\":\"test\"}",
        params: { enum: "has\"quotes", someString: "test" },
    }
])
operation EscapedStringValues {
    input: EscapedStringValuesInputOutput,
    output: EscapedStringValuesInputOutput,
}

list NonSparseList {
    member: String,
}

map NonSparseMap {
    key: String,
    value: String,
}

structure NullInNonSparseOutput {
    list: NonSparseList,
    map: NonSparseMap,
}

@http(uri: "/null-in-non-sparse", method: "POST")
@httpResponseTests([
    {
        id: "NullInNonSparse",
        protocol: "aws.protocols#restJson1",
        code: 200,
        body: "{\"list\":[null,\"one\",null,\"two\",null],\"map\":{\"zero\":null,\"one\":\"1\"}}",
        params: { list: ["one", "two"], map: { "one": "1" } },
    }
])
operation NullInNonSparse {
    output: NullInNonSparseOutput,
}
+3 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.expectRustMetadata
import software.amazon.smithy.rust.codegen.util.doubleQuote
import software.amazon.smithy.rust.codegen.util.dq
import software.amazon.smithy.rust.codegen.util.getTrait
import software.amazon.smithy.rust.codegen.util.orNull

@@ -154,7 +155,7 @@ class EnumGenerator(
            writer.rustBlock("pub fn as_str(&self) -> &str") {
                writer.rustBlock("match self") {
                    sortedMembers.forEach { member ->
                        write("""$enumName::${member.derivedName()} => "${member.value}",""")
                        write("""$enumName::${member.derivedName()} => ${member.value.dq()},""")
                    }
                    write("$enumName::$UnknownVariant(s) => s.as_ref()")
                }
@@ -182,7 +183,7 @@ class EnumGenerator(
            writer.rustBlock("fn from(s: &str) -> Self") {
                writer.rustBlock("match s") {
                    sortedMembers.forEach { member ->
                        write(""""${member.value}" => $enumName::${member.derivedName()},""")
                        write("""${member.value.dq()} => $enumName::${member.derivedName()},""")
                    }
                    write("other => $enumName::$UnknownVariant(other.to_owned())")
                }
+2 −2
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ import software.amazon.smithy.rust.codegen.smithy.generators.error.errorSymbol
import software.amazon.smithy.rust.codegen.smithy.generators.operationBuildError
import software.amazon.smithy.rust.codegen.smithy.locatedIn
import software.amazon.smithy.rust.codegen.smithy.meta
import software.amazon.smithy.rust.codegen.smithy.protocols.parse.SerdeJsonParserGenerator
import software.amazon.smithy.rust.codegen.smithy.protocols.parse.JsonParserGenerator
import software.amazon.smithy.rust.codegen.smithy.protocols.serialize.JsonSerializerGenerator
import software.amazon.smithy.rust.codegen.smithy.rustType
import software.amazon.smithy.rust.codegen.smithy.traits.InputBodyTrait
@@ -250,7 +250,7 @@ class BasicAwsJsonGenerator(
        val outputShape = operationIndex.getOutput(operationShape).get()
        val errorSymbol = operationShape.errorSymbol(symbolProvider)
        val jsonErrors = RuntimeType.awsJsonErrors(protocolConfig.runtimeConfig)
        val generator = SerdeJsonParserGenerator(protocolConfig)
        val generator = JsonParserGenerator(protocolConfig, AwsJsonHttpBindingResolver(model, awsJsonVersion))

        fromResponseFun(implBlockWriter, operationShape) {
            rustBlock("if #T::is_error(&response)", jsonErrors) {
+6 −0
Original line number Diff line number Diff line
@@ -59,6 +59,12 @@ interface HttpBindingResolver {
    fun requestMembers(operationShape: OperationShape, location: HttpLocation): List<MemberShape> =
        requestBindings(operationShape).filter { it.location == location }.map { it.member }

    /**
     * Returns a list of member shapes bound to a given response [location] for a given [operationShape]
     */
    fun responseMembers(operationShape: OperationShape, location: HttpLocation): List<MemberShape> =
        responseBindings(operationShape).filter { it.location == location }.map { it.member }

    /**
     * Determine the timestamp format based on the input parameters.
     */
+3 −3
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ import software.amazon.smithy.rust.codegen.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.generators.ProtocolConfig
import software.amazon.smithy.rust.codegen.smithy.generators.ProtocolGeneratorFactory
import software.amazon.smithy.rust.codegen.smithy.generators.ProtocolSupport
import software.amazon.smithy.rust.codegen.smithy.protocols.parse.SerdeJsonParserGenerator
import software.amazon.smithy.rust.codegen.smithy.protocols.parse.JsonParserGenerator
import software.amazon.smithy.rust.codegen.smithy.protocols.parse.StructuredDataParserGenerator
import software.amazon.smithy.rust.codegen.smithy.protocols.serialize.JsonSerializerGenerator
import software.amazon.smithy.rust.codegen.smithy.protocols.serialize.StructuredDataSerializerGenerator
@@ -83,7 +83,7 @@ class RestJson(private val protocolConfig: ProtocolConfig) : Protocol {
    override val defaultTimestampFormat: TimestampFormatTrait.Format = TimestampFormatTrait.Format.EPOCH_SECONDS

    override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator {
        return SerdeJsonParserGenerator(protocolConfig)
        return JsonParserGenerator(protocolConfig, httpBindingResolver)
    }

    override fun structuredDataSerializer(operationShape: OperationShape): StructuredDataSerializerGenerator {
Loading