swift 3 posting json parameter to api - json

I need to pass the following json to this function so Shopify Api can understand the submission.
Every time I execute this code, I get an error message that there is a missing required parameter. Obviously, I am unable to create the correct variable format and pass it to server.
Shopify API is expecting the following json to be passed via POST
{
"customer": {
"first_name": "Steve",
"last_name": "Lastnameson",
"email": "steve.lastnameson#example.com",
"verified_email": true,
"addresses": [
{
"address1": "123 Oak St",
"city": "Ottawa",
"province": "ON",
"phone": "555-1212",
"zip": "123 ABC",
"last_name": "Lastnameson",
"first_name": "Mother",
"country": "CA"
}
]
}
}
Here is my posting code:
let customer = [
"customer": [
"first_name": "Steve",
"last_name": "Lastnameson",
"email": "steve.lastnameson#example.com",
"verified_email": "true",
"addresses": [
[
"address1": "123 Oak St",
"city": "Ottawa",
"province": "ON",
"phone": "555-1212",
"zip": "123 ABC",
"last_name": "Lastnameson",
"first_name": "Mother",
"country": "CA",
],
],
],
] as [String: Any]
var request = URLRequest(url: URL(string: shopUrl + "/admin/customers.json")!)
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: customer, options: [])
URLSession.shared.dataTask(with:request, completionHandler: {(data, response, error) in
if error != nil {
print(error)
} else {
do {
guard let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] else { return }
guard let errors = json?["errors"] as? [[String: Any]] else { return }
if errors.count > 0 {
// show error
return
} else {
// show confirmation
}
}
}
}).resume()

The request needs to have the content type declared. Add:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

Related

Web API how to parse unicode json

I'm really confused by API of web service
Some blocks of data has a format like that:
"ja": "犯罪\u8005の子孫た\u3061が暮\u3089\u3059スラム\u8857\u3002\u5883界線の\u5411\u3053\u3046の人\u3005か\u3089は「族民」\u3068\u3055\u3052\u3059まれ\u3001差\u5225\u3092受\u3051\u3066\u3044た\u3002孤\u5150\u3060\u3063た少年・ルドは\u3001育\u3066の親\u3067\u3042るレグト\u3068\u5171にスラム\u8857に住み\u3001常人離れ\u3057た身体能力\u3092武\u5668に生計\u3092立\u3066\u3066\u3044た\u3002\u3060が\u3042る日\u3001身に覚\u3048のな\u3044罪\u3092\u7740せ\u3089れ\u3001スラムの人\u3005\u3067\u3055\u3048\u6050れる「\u5948落」\u3078\u3068落\u3068\u3055れ\u3066\u3057ま\u3046\u2026\u2026\u3002"
I realized that Swift do not work with those format. But I really don't know in what step I should convert this
My parse func:
URLSession
.shared
.dataTask(with: request) { data, response, error in
if let data = data {
do {
if let sanitisedData = String(data: data, encoding: .utf8)!.map({ String($0) }).filter({ $0 != "\\" }).joined(separator: "").replacingOccurrences(of: "U(.*?)", with: "\\\\u$1", options: .regularExpression).data(using: .utf8) {
let decoder = JSONDecoder()
let decodedResponse = try decoder.decode(Welcome.self, from: sanitisedData)
DispatchQueue.main.async {
self.data = decodedResponse
}
}
} catch let jsonError as NSError {
print("JSON Decode Failed: \(jsonError.localizedDescription)")
}
return
}
}
.resume()
Output:
JSON Decode Failed: The data couldn’t be read because it isn’t in the correct format.
I tried to convert this data to string and that's the result:
犯罪u8005の子孫たu3061が暮u3089u3059スラムu8857u3002u5883界線のu5411u3053u3046の人u3005かu3089は「族民」u3068u3055u3052u3059まれu3001差u5225u3092受u3051u3066u3044たu3002孤u5150u3060u3063た少年・ルドはu3001育u3066の親u3067u3042るレグトu3068u5171にスラムu8857に住みu3001常人離れu3057た身体能力u3092武u5668に生計u3092立u3066u3066u3044たu3002u3060がu3042る日u3001身に覚u3048のなu3044罪u3092u7740せu3089れu3001スラムの人u3005u3067u3055u3048u6050れる「u5948落」u3078u3068落u3068u3055れu3066u3057まu3046u2026u2026u3002
Example of response:
{
"result": "ok",
"response": "collection",
"data": [
{
"id": "f2e906bb-8329-4f93-af70-b6344f18aa07",
"type": "manga",
"attributes": {
"title": {
"en": "This players think i\u2019m one of them"
},
"altTitles": [
{
"ru": "Э\u0442\u0438 \u0438\u0433\u0440ок\u0438 \u0434\u0443м\u0430ю\u0442, \u0447\u0442о я о\u0434\u0438н \u0438\u0437 н\u0438\u0445"
}
],
"description": {
"en": "I am the Dark Lord. The one who united the demons. One who wields limitless power and might. The one who has had enough of it all.\n\nThese people have attacked our lands again!\n\nFor a hundred years now.... vile players have attacked our hellish lands, mercilessly plundering and killing peaceful demons.\n\nToday I will become human, infiltrate the ranks of humanity and destroy their rotten system from within... while these players think I'm one of them.",
"ru": "Я - \u0422\u0435мны\u0439 по\u0432\u0435л\u0438\u0442\u0435ль. \u0422о\u0442, к\u0442о о\u0431ъ\u0435\u0434\u0438н\u0438л \u0434\u0435моно\u0432. \u0422о\u0442, к\u0442о о\u0431л\u0430\u0434\u0430\u0435\u0442 \u0431\u0435\u0441кон\u0435\u0447но\u0439 \u0432л\u0430\u0441\u0442ью \u0438 \u0441\u0438ло\u0439. \u0422о\u0442, ком\u0443 \u0432\u0441\u0435 э\u0442о н\u0430\u0434о\u0435ло.\n\nЭ\u0442\u0438 лю\u0434\u0438 \u0432 о\u0447\u0435\u0440\u0435\u0434но\u0439 \u0440\u0430\u0437 н\u0430п\u0430л\u0438 н\u0430 н\u0430\u0448\u0438 \u0437\u0435мл\u0438!\n\n\u0412о\u0442 \u0443\u0436\u0435 \u0441о\u0442ню л\u0435\u0442\u2026. М\u0435\u0440\u0437к\u0438\u0435 \u0438\u0433\u0440ок\u0438 \u0430\u0442\u0430к\u0443ю\u0442 н\u0430\u0448\u0438 \u0430\u0434\u0441к\u0438\u0435 \u0437\u0435мл\u0438, \u0431\u0435\u0441по\u0449\u0430\u0434но \u0433\u0440\u0430\u0431я \u0438 \u0443\u0431\u0438\u0432\u0430я м\u0438\u0440ны\u0445 \u0434\u0435моно\u0432.\n\n\u0412н\u0435\u0441\u0438\u0442\u0435 Э\u0422О!\n\n\u0421\u0435\u0433о\u0434ня я \u0441\u0442\u0430н\u0443 \u0447\u0435ло\u0432\u0435ком, п\u0440о\u0431\u0435\u0440\u0443\u0441ь \u0432 \u0440я\u0434ы \u0447\u0435ло\u0432\u0435\u0447\u0435\u0441\u0442\u0432\u0430 \u0438 \u0443н\u0438\u0447\u0442о\u0436\u0443 \u0438\u0445 п\u0440о\u0433н\u0438\u0432\u0448\u0443ю \u0441\u0438\u0441\u0442\u0435м\u0443 \u0438\u0437н\u0443\u0442\u0440\u0438... пок\u0430 э\u0442\u0438 \u0438\u0433\u0440ок\u0438 \u0434\u0443м\u0430ю\u0442, \u0447\u0442о я о\u0434\u0438н \u0438\u0437 н\u0438\u0445."
},
"isLocked": false,
"links": {
"raw": "https://remanga.org/manga/this-players-think-im-one-of-them?subpath=about"
},
"originalLanguage": "ru",
"lastVolume": "",
"lastChapter": "",
"publicationDemographic": "seinen",
"status": "ongoing",
"year": 2022,
"contentRating": "suggestive",
"tags": [
{
"id": "36fd93ea-e8b8-445e-b836-358f02b3d33d",
"type": "tag",
"attributes": {
"name": {
"en": "Monsters"
},
"description": [],
"group": "theme",
"version": 1
},
"relationships": []
},
{
"id": "391b0423-d847-456f-aff0-8b0cfc03066b",
"type": "tag",
"attributes": {
"name": {
"en": "Action"
},
"description": [],
"group": "genre",
"version": 1
},
"relationships": []
},
{
"id": "39730448-9a5f-48a2-85b0-a70db87b1233",
"type": "tag",
"attributes": {
"name": {
"en": "Demons"
},
"description": [],
"group": "theme",
"version": 1
},
"relationships": []
},
{
"id": "3e2b8dae-350e-4ab8-a8ce-016e844b9f0d",
"type": "tag",
"attributes": {
"name": {
"en": "Long Strip"
},
"description": [],
"group": "format",
"version": 1
},
"relationships": []
},
{
"id": "87cc87cd-a395-47af-b27a-93258283bbc6",
"type": "tag",
"attributes": {
"name": {
"en": "Adventure"
},
"description": [],
"group": "genre",
"version": 1
},
"relationships": []
},
{
"id": "a1f53773-c69a-4ce5-8cab-fffcd90b1565",
"type": "tag",
"attributes": {
"name": {
"en": "Magic"
},
"description": [],
"group": "theme",
"version": 1
},
"relationships": []
},
{
"id": "cdc58593-87dd-415e-bbc0-2ec27bf404cc",
"type": "tag",
"attributes": {
"name": {
"en": "Fantasy"
},
"description": [],
"group": "genre",
"version": 1
},
"relationships": []
},
{
"id": "e197df38-d0e7-43b5-9b09-2842d0c326dd",
"type": "tag",
"attributes": {
"name": {
"en": "Web Comic"
},
"description": [],
"group": "format",
"version": 1
},
"relationships": []
},
{
"id": "f5ba408b-0e7a-484d-8d49-4e9125ac96de",
"type": "tag",
"attributes": {
"name": {
"en": "Full Color"
},
"description": [],
"group": "format",
"version": 1
},
"relationships": []
}
],
"state": "published",
"chapterNumbersResetOnNewVolume": false,
"createdAt": "2022-01-10T17:15:53+00:00",
"updatedAt": "2022-01-10T17:26:26+00:00",
"version": 4,
"availableTranslatedLanguages": [
"ru"
]
},
"relationships": [
{
"id": "5537d8ed-16ed-4f6f-af75-ad7d7edb2ddc",
"type": "author"
},
{
"id": "36ca9e78-35a9-474d-b4e6-0e4065f0af87",
"type": "artist"
},
{
"id": "93e21cc1-1f61-46ce-8362-90d9d6888f63",
"type": "artist"
},
{
"id": "0e703bf4-1996-432c-8620-3c08f2edb37b",
"type": "cover_art"
}
]
}
],
"limit": 1,
"offset": 0,
"total": 57
}
If your server response is really without the unicode escaped, that is,
"犯罪\u8005の子孫た\u3061 ...", then try escaping the data as shown in this example code,
to get: "犯罪\\u8005の子孫た\\u3061 ..." (note the \\) and decode it like this:
URLSession
.shared
.dataTask(with: request) { data, response, error in
if let data = data {
do {
if let sanitisedData = String(data: data, encoding: .utf8)!
.replacingOccurrences(of: "\\", with: "\\\\") // <-- here
.data(using: .utf8) {
let decoder = JSONDecoder()
let decodedResponse = try decoder.decode(Welcome.self, from: sanitisedData)
DispatchQueue.main.async {
self.data = decodedResponse
}
}
} catch let jsonError as NSError {
print("JSON Decode Failed: \(jsonError.localizedDescription)")
}
return
}
}.resume()
EDIT-1:
you may also need to do this: .replacingOccurrences(of: "\n", with: "\\n")
You don't need to process the data returned at all if the result is simply a text (string to say welcome someone). My solution below is just loading a JSON file returned (as you mentioned above) and then decode the data to Welcome object below
struct Welcome: Codable {
let ja: String
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
ja = try values.decodeIfPresent(String.self, forKey: .ja) ?? ""
}
}
func readJsonFile(filename: String) -> String {
guard let fileUrl = Bundle.main.url(forResource: filename, withExtension: "json") else { fatalError() }
guard let jsonData = try? String(contentsOf: fileUrl) else {
return ""
}
return jsonData
}
func parseJsonFile() {
let jsonStr = readJsonFile(filename: "data")
let jsonData: Data = Data(jsonStr.utf8)
let decoder = JSONDecoder()
do {
let welcome = try decoder.decode(Welcome.self, from: jsonData)
print("\(welcome.ja)")
} catch {
print(error.localizedDescription)
}
}
this is the result when I print the welcome.ja's value:
犯罪者の子孫たちが暮らすスラム街。境界線の向こうの人々からは「族民」とさげすまれ、差別を受けていた。孤児だった少年・ルドは、育ての親であるレグトと共にスラム街に住み、常人離れした身体能力を武器に生計を立てていた。だがある日、身に覚えのない罪を着せられ、スラムの人々でさえ恐れる「奈落」へと落とされてしまう……。

Failed to get a Wordpress JSON

I have a problem with a JSON that I recover from a site with WordPress, the problem is that when I try to consult the JSON, my query does not return anything.
I tried using Alamofire to recover my JSON but it does not work either, I do not know how to recover the JSON that returns my site with WordPress
I have tried to recover the JSON in the following way but it does not work, it does not return anything:
let urlString = URL(string: "https://www.sitioWeb.org.mx/wp-json/wp/v2/posts?per_page=100&tags=(id)")
let request = URLRequest(url: urlString!)
let task = URLSession.shared.dataTask(with: request){data, response, error in
guard let data = data else{
print("Solicitud fallida \(error!)")
return
}
do{
print("Recibimos respuesta")
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: String]{
DispatchQueue.main.async {
let titulo = json["rendered"]
let content = json["content"]
let excerpt = json["excerpt"]
print(json)
print(titulo!)
print(content!)
print(excerpt!)
}
}
}catch let parseError {
print("Error al parsear: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("respuesta: \(responseString!)")
}
}
task.resume()
I have also tried with Alamofire in the following way:
Alamofire.request("https://www.sitioWeb.org.mx/wp-json/wp/v2/posts?per_page=100&tags=(id)").responseJSON(completionHandler: { response in
if let json = response.result.value as? JSON{
print(json)
}
})
But it still does not work.
This is the structure that JSON has:
[ {
"id": 3438,
"date": "2019-04-01T06:02:50",
"date_gmt": "2019-04-01T12:02:50",
"guid": {
"rendered": "https://sitioWeb.org.mx/?p=3438"
},
"modified": "2019-04-01T06:02:50",
"modified_gmt": "2019-04-01T12:02:50",
"slug": "documento-2019",
"status": "publish",
"type": "post",
"link": "https://sitioWeb.org.mx/documento-2019 /",
"title": {
"rendered": "Documento 2019"
},
"content": {
"rendered": "https://sitioWeb.org.mx/wp-content/uploads/2019/04/document.pdf \" class=\"pdfemb-viewer\" style=\"\" data-width=\"max\" data-height=\"max\" data-mobile-width=\"500\" data-scrollbar=\"none\" data-download=\"off\" data-tracking=\"on\" data-newwindow=\"on\" data-pagetextbox=\"off\" data-scrolltotop=\"off\" data-startzoom=\"100\" data-startfpzoom=\"100\" data-toolbar=\"bottom\" data-toolbar-fixed=\"off\">document.pdf \n",
"protected": false
},
"excerpt": {
"rendered": "",
"protected": false
},
"author": 1,
"featured_media": 0,
"comment_status": "closed",
"ping_status": "closed",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
39
],
"tags": [
54,
55
],
"_links": {
"self": [
{
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/posts/3438"
}
],
"collection": [
{
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/posts"
}
],
"about": [
{
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/types/post"
}
],
"author": [
{
"embeddable": true,
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/users/1"
}
],
"replies": [
{
"embeddable": true,
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/comments?post=3438"
}
],
"version-history": [
{
"count": 1,
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/posts/3438/revisions"
}
],
"predecessor-version": [
{
"id": 3440,
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/posts/3438/revisions/3440"
}
],
"wp:attachment": [
{
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/media?parent=3438"
}
],
"wp:term": [
{
"taxonomy": "category",
"embeddable": true,
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/categories?post=3438"
},
{
"taxonomy": "post_tag",
"embeddable": true,
"href": "https://sitioWeb.org.mx/wp-json/wp/v2/tags?post=3438"
}
],
"curies": [
{
"name": "wp",
"href": "https://api.w.org/{rel}",
"templated": true
}
]
} }]
The console does not return any errors on the JSON
The correct type is [[String: Any]].
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]]
To get the URL for the author, drill down into the JSON like this:
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
if let links = json[0]["links"] as? [[String: Any]] {
if let author = links[0]["author"]? as? [String: Any] {
if let authorURL = author["href"] as? String {
}
}
}
}

Decoding JSON with Codable issue. keyNotFound error message

I have problem with decoding JSON. I am trying to decode my JSON with
let temp = try JSONDecoder().decode([LastTemperatureResponse].self, from: data).
My Codable structs is following:
struct LastTemperatureResponseElement: Codable {
let measurement: Measurement
}
struct Measurement: Codable {
let ts: String
let sensors: [VportSensor]
}
struct VportSensor: TemperatureSensor, Codable {
var lastUpdate: String!
let address, description: String
let status: String
let temperature: Double
}
Well, if I'm trying to decode my JSON, I am getting error message where it's quite clear
keyNotFound(CodingKeys(stringValue: "status", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "measurement", intValue: nil), CodingKeys(stringValue: "sensors", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"status\", intValue: nil) (\"status\").", underlyingError: nil))
but please take a look on my JSON
[
{
"type": "temperatures",
"ts": "2017-11-08T16:43:59.558Z",
"source": "thermo-king",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2017-11-08T16:43:18.000Z",
"sensors": [
{
"address": "t1",
"description": "LFTest1",
"setpoints": [
{
"address": "s1",
"name": "LFSTest1"
}
]
},
{
"address": "t2",
"description": "LFTest2",
"setpoints": [
{
"address": "s2",
"name": "LFSTest2"
}
]
},
{
"address": "t3",
"description": "LFTest3",
"setpoints": [
{
"address": "s3",
"name": "LFSTest3"
}
]
},
{
"address": "t4",
"description": "LFTest4"
},
{
"address": "t5",
"description": "LFTest5"
},
{
"address": "t6",
"description": "LFTest6"
}
],
"sensor": {
"address": "t1",
"name": "LFTest1"
},
"setpoints": [
{
"address": "s1",
"name": "LFSTest1"
}
]
}
},
{
"type": "temperatures",
"ts": "2018-06-07T07:05:38.962Z",
"source": "1-wire",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2018-06-07T07:05:31.000Z",
"sensors": [
{
"address": "2839A5B104000004",
"description": "1-wire #1",
"status": "ok",
"temperature": 24.8
},
{
"address": "28EFBAB104000061",
"description": "1-wire #3",
"status": "ok",
"temperature": 24.5
},
{
"address": "2845F6B504000034",
"description": "1-wire #2",
"status": "ok",
"temperature": 24.5
}
],
"sensor": {
"address": "2839A5B104000004",
"name": "1-wire #1",
"status": "ok"
},
"temperature": 24.8
}
},
{
"type": "temperatures",
"ts": "2018-06-07T07:11:50.030Z",
"source": "vport",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2018-06-07T07:11:47.000Z",
"sensors": [
{
"address": "1036040010",
"description": "Vport 1-wire",
"status": "high",
"temperature": 26
}
],
"sensor": {
"address": "1036040010",
"name": "Vport 1-wire",
"status": "high"
},
"temperature": 26
}
}
]
So I can guess that is giving error because of first portion of data, but should it be omitted and data generated with the rest?
After tracing your issue, I figured that there is couple of issues, First of all:
You are NOT declaring optionals:
based on the attached json, it seems that there are some of the properties that do not always exist, such as:
status => VportSensor.
temperature => Measurement.
temperature => VportSensor.
temperature => setpoints.
you would need make sure to declare any property that may not received as optional.
Also, The implementation of the Codeable structs:
the implemented structs seem to be not typical to the json response structure, make sure to declare your codable structs to be matched with the received json structure.
Note That:
lastUpdate and description are not used in VportSensor.
Based on my answer, there is no need to TemperatureSensor...
Tip:
When it comes to working with dates (such as ts), you should declare it directly as Date instead of String and then set the convenient dateDecodingStrategy. In your case, it should be a custom one, you could find how to do it in this answer.
Implementation:
Based on the above description, there is the full implementation:
struct Main: Codable {
let type: String
let ts: Date
let source: String
let unit: Unit
let measurement: Measurement
}
struct Unit: Codable {
var number: String
}
struct Measurement: Codable {
let ts: String
let sensors: [VportSensor]
let sensor: VportSensor
let temperature: Double?
}
struct LastTemperatureResponseElement: Codable {
let measurement: Measurement
}
struct VportSensor: Codable {
//let lastUpdate: String!
//let description: String
let address: String
let name: String?
let status: String?
let temperature: Double?
let setpoints: [Setpoint]?
}
struct Setpoint: Codable {
let address: String
let name: String
}
// this part from the mentioned answer for creating custom `dateDecodingStrategy`:
enum DateError: String, Error {
case invalidDate
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
let dateStr = try container.decode(String.self)
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
throw DateError.invalidDate
})
Output:
let decoder = JSONDecoder()
do {
let temp = try decoder.decode([Main].self, from: json)
// here we go, `temp` is an array of main object of the json
} catch {
print(error)
}
If you are wondering what is json in the
let temp = try decoder.decode([Main].self, from: json)
I just took the attached json response and add it into Data Object:
let json = """
[
{
"type": "temperatures",
"ts": "2017-11-08T16:43:59.558Z",
"source": "thermo-king",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2017-11-08T16:43:18.000Z",
"sensors": [
{
"address": "t1",
"description": "LFTest1",
"setpoints": [
{
"address": "s1",
"name": "LFSTest1"
}
]
},
{
"address": "t2",
"description": "LFTest2",
"setpoints": [
{
"address": "s2",
"name": "LFSTest2"
}
]
},
{
"address": "t3",
"description": "LFTest3",
"setpoints": [
{
"address": "s3",
"name": "LFSTest3"
}
]
},
{
"address": "t4",
"description": "LFTest4"
},
{
"address": "t5",
"description": "LFTest5"
},
{
"address": "t6",
"description": "LFTest6"
}
],
"sensor": {
"address": "t1",
"name": "LFTest1"
},
"setpoints": [
{
"address": "s1",
"name": "LFSTest1"
}
]
}
},
{
"type": "temperatures",
"ts": "2018-06-07T07:05:38.962Z",
"source": "1-wire",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2018-06-07T07:05:31.000Z",
"sensors": [
{
"address": "2839A5B104000004",
"description": "1-wire #1",
"status": "ok",
"temperature": 24.8
},
{
"address": "28EFBAB104000061",
"description": "1-wire #3",
"status": "ok",
"temperature": 24.5
},
{
"address": "2845F6B504000034",
"description": "1-wire #2",
"status": "ok",
"temperature": 24.5
}
],
"sensor": {
"address": "2839A5B104000004",
"name": "1-wire #1",
"status": "ok"
},
"temperature": 24.8
}
},
{
"type": "temperatures",
"ts": "2018-06-07T07:11:50.030Z",
"source": "vport",
"unit": {
"number": "1226000743"
},
"measurement": {
"ts": "2018-06-07T07:11:47.000Z",
"sensors": [
{
"address": "1036040010",
"description": "Vport 1-wire",
"status": "high",
"temperature": 26
}
],
"sensor": {
"address": "1036040010",
"name": "Vport 1-wire",
"status": "high"
},
"temperature": 26
}
}
]
""".data(using: .utf8)!
You can easily skip the keys those are not getting from server response.
Example JSON response is:
{
"isValid": false,
"pendingAttempts": 2
}
In this json response there is missing "id" field & in our code we have declared it. So we can easily skip it by the following code.
//Code example
struct ResponseModel: Codable {
var id: String? //misng in response
var isValid: Bool?
var token: String?
//initializer
init(id: String?, isValid: Bool?, token: String?) {
self.id = id
self.isValid = isValid
self.token = token
}
//definging the coding keys
enum ResponseModelCodingKeys: String, CodingKey {
//The right hand side keys should be same as of json response keys
case id = "id"
case isValid = "isValid"
case token = "token"
}
//decoding initializer
init(from decoder: Decoder) throws {
var id: String?
var isValid: Bool?
var token: String?
let container = try decoder.container(keyedBy: ResponseModelCodingKeys.self) // defining our (keyed) container
do {
//if found then map
id = try container.decode(String.self, forKey: .id)
}
catch {
//not found then just set the default value
/******** This case will be executed **********/
id = ""
}
do {
//if found then map
isValid = try container.decode(Bool.self, forKey: .isValid)
}
catch {
//not found then just set the default value
isValid = false
}
do {
//if found then map
token = try container.decode(String.self, forKey: .token)
}
catch {
//not found then just set the default value
token = ""
}
//Initializing the model
self.init(id: id, isValid: isValid, token: token)
}
}
This technique is useful when we have common response for multiple API's & each API have some missing keys.

posting nested JSON in Swift with Alamofire

Good day I am currently struggling to post data to my backend I am new to swift development please help
The API expects me to send following structure:
{
"oid": "string",
"businessKey": "string",
"refNumber": "string",
"name": "string",
"cost": "string",
"clientOid": "string",
"vehicleOid": "string",
"driverOid": "string",
"from": {
"oid": "string",
"businessKey": "string",
"coordinates": [
"string"
],
"address": "string"
},
"to": {
"oid": "string",
"businessKey": "string",
"coordinates": [
"string"
],
"address": "string"
},
"when": "2018-04-09T10:03:01.156Z",
"atp": "2018-04-09T10:03:01.156Z",
"eta": "2018-04-09T10:03:01.156Z",
"ata": "2018-04-09T10:03:01.156Z",
"droplets": [
{
"oid": "string",
"businessKey": "string",
"itemOid": "string",
"description": "string",
"notes": "string"
}
],
"serviceRating": 0,
"notes": "string"
}
This is how is my code:
func createDrop(oid: String, token: String){
let url = getCar.url
let token = "Bearer " + token
var request = URLRequest(url: URL(string: "\(url)drops")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue( token, forHTTPHeaderField: "Authorization")
var parameters: Dictionary<String, Any> = [
"name": "Thami",
"notes": "New",
"cost": "totalPrice",
"clientOid": "clientOi",
"vehicleOid": "vehicleOi",
"driverOid": "driverO",
"when": "dropTime",
"atp": "dropTime",
"eta": "dropTime",
"ata": "dropTime",
"from":[
"coordinates": [
"-26.002483",
"28.099503"
],
"address": "his.distanceInfo.getPickUp()",
],
"to":[
"coordinates": [
"-26.002483",
"28.099503"
],
"address": "this.distanceInfo.getDestination()",
],
"droplets":[
"itemOid": "575ae6bd30bc5d5017477143",
"notes": "new"
]
]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
print("serilizing json")
} catch {
print("JSON serialization failed: \(error)")
}
print(parameters)
Alamofire.request(request).responseJSON {(response) in
debugPrint(response)
if response.response?.statusCode == 200 {
print ("pass")
let dropJSON : JSON = JSON(response.result.value!)
print(dropJSON)
}else{
print ("fail gfgdfds")
let dErrorJSON : JSON = JSON(response.result.error!)
print(dErrorJSON)
}
}
}
This is the error i am getting:
[Result]: FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
how can I format my object to perform this post
Try to encode the parameters in your request like
Alamofire.request("https://httpbin.org/post", method: .post, parameters: parameters, encoding: JSONEncoding.default)
Check the docs to get more encoding information
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#json-encoding

How to fetch values from JSON response in swift?

How to fetch values from JSON response in swift? Here i want to loop the order object values inorder to get the dictionary values based on their key. Can anyone suggest me a solution please.
{
"order": [
"abc",
"def",
"ghi",
],
"posts": {
"abc": {
"id": "abc",
"user_id": "q",
"channel_id": "qwer",
"message": "dsd"
},
"def": {
"id": "def",
"user_id": "w",
"channel_id": "werg",
"message": "Gg"
},
"ghi": {
"id": "ghi",
"user_id": "v",
"channel_id": "bnm",
"message": "Ss"
}
}
}
Here's what you can do, Change your JSON string into Data using String.Encoding.utf8 encoding
Then applying JSONSerialization and convert it into Dictionary/Array:
let jsonText = """
{
"order": [
"abc",
"def",
"ghi",
],
"posts": {
"abc": {
"id": "abc",
"user_id": "q",
"channel_id": "qwer",
"message": "dsd"
},
"def": {
"id": "def",
"user_id": "w",
"channel_id": "werg",
"message": "Gg"
},
"ghi": {
"id": "ghi",
"user_id": "v",
"channel_id": "bnm",
"message": "Ss"
}
}
}
"""
var dictionary: [String: Any]?
if let data = jsonText.data(using: String.Encoding.utf8) {
do {
dictionary = try JSONSerialization.jsonObject(with: data, options: [.allowFragments,.mutableLeaves]) as? [String: Any]
if let myDictionary = dictionary {
let posts = myDictionary["posts"] as? [String: Any]
print(posts)
print(posts?["abc"] as? [String: Any])
}
} catch let error as NSError {
print(error)
}
}
To get the message based on order you can do:
let orders = (dictionary?["order"] as? [String]) ?? []
//message for abc
var posts = dictionary?["posts"] as? [String: Any]
var post = posts?[orders.first ?? ""] as? [String: Any]
var message = post?["message"]
print(message)
Check the apple documentation on NSJSONSerialization