When I call a service (POST) from Postman I get proper JSON:
{
“XResponse": {
“xValue1”: “01”,
“xClearance": null,
“xValue2”: “02”,
“xValue3”: “19.95”,
“xEvents": [
{
“x_comment_1": null,
“x_comment_2”: null
}
],
“x_id": "0073"
}
}
But when I call it from my Swift I get: (from print("JSON: (xRaw)”)). It appears to be missing quotes in several places.
{
XResponse = {
“xValue1” = 01;
xClearance = "<null>";
“xValue2” = 02;
“xValue3” = 19.95;
“xEvents" = (
{
“x_comment_1" = "<null>";
“x_comment_2" = "<null>";
}
);
“x_id" = 0073;
};
})
ViewController.swift
DataService.shared.fetchX(loc: “00001”){ (result) in
DispatchQueue.main.async {
switch result {
case .success(let xRaw):
print("JSON: \(xRaw)")
}
case .failure(let error):
print(error)
}
}
}
DataService.swift
func fetchX(loc: String, completion: @escaping (Result<Any, Error>) -> Void) {
var postAuth: String
let postComponents = createXURLComponents()
guard let validURL = postComponents.url else {
print("URL creation failed")
return
}
postAuth = locals.authStringXDEV
var postRequest = URLRequest(url: validURL, timeoutInterval: Double.infinity)
let authString = postAuth
postRequest.addValue("Basic \(authString)", forHTTPHeaderField: "Authorization")
postRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
postRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let parameters = "{\r\n \”XRequest\": {\r\n \”XY_id\": \(loc)\r\n }\r\n}"
let postData = parameters.data(using: .utf8)
postRequest.httpMethod = "POST"
postRequest.httpBody = postData
URLSession.shared.dataTask(with: postRequest) { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
print("getXInfo Response status: \(httpResponse.statusCode)")
}
guard let validData = data, error == nil else {
completion(.failure(error!))
return
}
do {
let xData = try JSONSerialization.jsonObject(with: validData)
completion(.success(xData))
} catch let serializationError {
print("localizedDescription: \(serializationError.localizedDescription)")
completion(.failure(serializationError))
}
}.resume()
}
Ultimately I would like to return an object which conforms to a struct I have created, but when I try to JSONDecoder().decode
I get the following error:
localizedDescription: The data couldn’t be read because it isn’t in the correct format. typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))
I am assuming the error is in the underlying JSON.
Thanks.
Please note that this code is heavily hand-edited.
The struct I have defined is:
import Foundation
struct XResponse: Encodable {
var xClearance: String?
var xValue1: String
var xValue2: String?
var xValue3: String?
var x_id: String
var xEvents: XX_Events?
enum CodingKeys: String, CodingKey {
case xValue1, xValue2, xValue3, x_id, xClearance, xEvents
}
}
extension XResponse: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.xClearance = try container.decodeIfPresent(String.self, forKey: .xClearance)
self.xValue1 = try container.decode(String.self, forKey: .xValue1)
self.xValue2 = try container.decodeIfPresent(String.self, forKey: .xValue2 )
self.x_id = try container.decode(String.self, forKey: .x_id )
self.xValue3 = try container.decodeIfPresent(String.self, forKey: .xValue3 )
self.xEvents = try container.decodeIfPresent(XX_Events.self, forKey: .xEvents )
}
}
struct XX_Events: Encodable {
var x_comment_1: String? // null,
var x_comment_2: String? // null,
enum CodingKeys: String, CodingKey {
case x_comment_1, x_comment_2
}
}
extension XX_Events: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.x_comment_1 = try container.decodeIfPresent(String.self, forKey: .x_comment_1)
self.x_comment_2 = try container.decodeIfPresent(String.self, forKey: .x_comment_2)
}
}