diff --git a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift index 42c660101..f04700a39 100644 --- a/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift +++ b/Sources/SmithyJSON/Reader/Reader+JSONDeserialization.swift @@ -6,19 +6,19 @@ // import struct Foundation.Data -import class Foundation.NSError import class Foundation.JSONSerialization -import class Foundation.NSNull extension Reader { public static func from(data: Data) throws -> Reader { + // Empty bodies are allowed. When the body is empty, + // return a reader with no JSON content. guard !data.isEmpty else { return Reader(nodeInfo: "", parent: nil) } - do { - let jsonObject = try JSONSerialization.jsonObject(with: data, options: [.fragmentsAllowed]) - return try Reader(nodeInfo: "", jsonObject: jsonObject) - } catch let error as NSError where error.domain == "NSCocoaErrorDomain" && error.code == 3840 { - return try Reader(nodeInfo: "", jsonObject: [:]) - } + + // Attempt to parse JSON from the non-empty body. + // Throw an error if JSON is invalid. + // (Determine whether to wrap this error) + let jsonObject = try JSONSerialization.jsonObject(with: data) + return try Reader(nodeInfo: "", jsonObject: jsonObject) } } diff --git a/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift b/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift index 8cb8135df..55c463568 100644 --- a/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift +++ b/Tests/ClientRuntimeTests/OrchestratorTests/OrchestratorTests.swift @@ -223,10 +223,11 @@ class OrchestratorTests: XCTestCase { .attributes(attributes) .serialize({ input, builder, _ in trace.append("serialize") + let data = try JSONEncoder().encode(["foo": input.foo]) builder.withMethod(.get) .withPath("/") .withHost("localhost") - .withBody(.data(try! JSONEncoder().encode(input.foo))) + .withBody(.data(data)) }) .deserialize({ response, _ in trace.append("deserialize") @@ -234,8 +235,8 @@ class OrchestratorTests: XCTestCase { guard case let .data(data) = response.body else { return TestOutput(bar: "") } - let bar = try! JSONDecoder().decode(String.self, from: data!) - return TestOutput(bar: bar) + let object = try! JSONDecoder().decode([String: String].self, from: data!) + return TestOutput(bar: object["foo"]!) } else { let responseReader = try SmithyJSON.Reader.from(data: try await response.data()) let baseError = try TestBaseError(httpResponse: response, responseReader: responseReader, noErrorWrapping: true) @@ -1373,7 +1374,8 @@ class OrchestratorTests: XCTestCase { let orchestrator = traceOrchestrator(trace: trace) .retryStrategy(DefaultRetryStrategy(options: RetryStrategyOptions(backoffStrategy: ImmediateBackoffStrategy()))) .serialize({ (input: TestInput, builder: HTTPRequestBuilder, context) in - builder.withBody(.data(Data("\"\(input.foo)\"".utf8))) + let data = try JSONEncoder().encode(["foo": input.foo]) + builder.withBody(.data(data)) }) .executeRequest(executeRequest) let result = await asyncResult {