Parse Json to nested Struct using Swift - json

I am trying to parse a JSON that I am receiving in my Application. The JSON Syntax is correct but I am unable to parse it into a nested Struct.
Here is my code that can be run in Playground:
let message = "{\"type\":\"something\",\"data\":{\"one\":\"first\",\"two\":\"second\",\"three\":\"third\"}}"
let jsonData = message.data(using: .utf8)!
struct Message: Decodable {
let type: String
struct data: Decodable {
var one: String
var two: String
var three: String
}
}
let receivedMessage: Message = try! JSONDecoder().decode(Message.self, from: jsonData)
The printed Result is Message(type: "something") but the data is not parsed.
How can I parse the data correctly to use it afterwards.

The nested struct/dictionary is the value for key data
struct Message: Decodable {
let type: String
let data: Nested
struct Nested: Decodable {
var one: String
var two: String
var three: String
}
}

Related

How to deserialize below JSON response in swift?

I have a json response. I'm bit confused on how to deserialize it. I want to extract the Id and Name from the below json response and store them as key value pairs in a dictionary.
JSON Response
("[{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01234\"},\"Id\":\"01234\",\"Name\":\"User1\",\"RecordTypeId\":\"1\"},{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01235\"},\"Id\":\"01235\",\"Name\":\"User2\",\"RecordTypeId\":\"2\"},{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01236\"},\"Id\":\"01236\",\"Name\":\"User3\",\"RecordTypeId\":\"3\"},{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01237\"},\"Id\":\"01237\",\"Name\":\"User4\",\"RecordTypeId\":\"4\"}]")
I want to extract the id and name values from above json response and store them in a dictionary like below
dict = [01234:"User1", 01235:"User2", 01236:"User3", 01237:"User4"]
The server's response seems like an array, so you could deserialize it to something like [String].
Then you define a structure that corresponds to the json inside that array, something like this:
struct ResponseElement: Codable {
struct attributes : Codable {
let type, url: String
}
let Id, Name, RecordTypeId: String
}
After that you decode it using this: JSONDecoder().decode([ResponseElement].self, ...
Finally you go over every element in your JSON to fill the dictionary, which has the following type [Int:String]
I tested this on Playgrounds, the full code is:
import Foundation
let serverResponse: [String] = [
"[{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01234\"},\"Id\":\"01234\",\"Name\":\"User1\",\"RecordTypeId\":\"1\"},{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01235\"},\"Id\":\"01235\",\"Name\":\"User2\",\"RecordTypeId\":\"2\"},{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01236\"},\"Id\":\"01236\",\"Name\":\"User3\",\"RecordTypeId\":\"3\"},{\"attributes\":{\"type\":\"User\",\"url\":\"/services/data/v1.0/objects/User/01237\"},\"Id\":\"01237\",\"Name\":\"User4\",\"RecordTypeId\":\"4\"}]"
]
struct ResponseElement: Codable {
struct attributes : Codable {
let type, url: String
}
let Id, Name, RecordTypeId: String
}
var dict:[Int:String] = [:]
if let serverResponseAsData = serverResponse[0].data(using: .utf8),
let response = try? JSONDecoder().decode([ResponseElement].self, from: serverResponseAsData) {
response.forEach { element in
if let idAsInt = Int(element.Id) {
dict[idAsInt] = element.Name
}
}
}
print(dict)
And this prints:
[1235: "User2", 1237: "User4", 1236: "User3", 1234: "User1"]

How to get json array from json object in SWIFT?

Hello friends I need your help for reading the array from the json object.
like
{"info":[{"memoID":"3","memoName":"Hello"}]}
using SwiftyJSON
when I'm in android I can use
JSONArray array = object.getJSONArray(“info”);
JSONDecoder
let content = try? JSONDecoder().decode(Root.self , from: data)
print(content)
// MARK: - Empty
struct Root: Codable {
let info: [Info]
}
// MARK: - Info
struct Info: Codable {
let memoID, memoName: String
}
SwiftyJson
if let res = arr["info"].array { // arr is of type JSON
print(res)
}

how to convert JSON dictionary to string value in swift 4

I'm new to Swift and I started working on a Swift 4 project with a PHP server.
I use Alamofire for requests, and print the data using print(). This is is what i'm getting:
{"error":false,"n":"Raghad"}
But when I want to convert it to String, it returns "" (empty) and
when I convert to boolean it returns the value correctly.
So, how can I fix it?
let wJSON : JSON = JSON(response.result.value!)
print(wJSON["n"].stringValue)
print(wJSON["error"].boolValue)
Simple solution using Decodable, define a Struct that conforms to the Decodable protocol for your dictionary
struct Reply: Decodable {
let error: Bool
let n: String
}
let data = response.data
do {
let result = try JSONDecoder().decode(Reply.self, from: data)
print("\(result.n) \(result.error)")
} catch {
print(error)
}
I change the responseString to responseJSON
Alamofire.request(Url!, method: .post, parameters: par).validate().responseJSON { response in if response.result.isSuccess { let wJSON : JSON = JSON(response.result.value!)
and it's work

how to loop through structs?

I'm fetching data from coinDesk API to get bitcoin rate related to other currencies, I've created 3 structs to save this data, but it's not possible to loop through the struct to know how many items I have there...
that's my structure:
struct Response: Codable {
var bpi: currencies
}
struct currencies: Codable {
var USD: info
var GBP: info
var EUR: info
}
struct info: Codable {
var code: String
var symbol: String
var description: String
var rate_float: Float
}
To save the data from API I just use:
let jsonData = try JSONDecoder().decode(Response.self, from: data)
It saves the data with no error but, when I try to loop through this data to populate tableViewCells it doesn't work.
what I'm doing know is...
let euro = jsonData.bpi.EUR
let dollar = jsonData.bpi.USD
let gbp = jsonData.bpi.GBP
let infos = [euro,dollar,gbp]
completion(infos)
This is sending the data to my UITableView and populating, but what if I had 500 currencies? it would not be practical at all.. how could I do this in a more effective way?
Thank you in advance for the answers.
Don't put keys instead
struct Response: Codable {
let bpi: [String:Info]
}
struct Info: Codable {
let code: String
let symbol: String
let description: String
let rate_float: Float
}
Then
let jsonData = try JSONDecoder().decode(Response.self, from: data)
print(jsonData.bpi["USD"])
so for all keys
let keys = Array(jsonData.bpi.keys)
let values = Array(jsonData.bpi.values)

Using Swift 4 Decodable to parse JSON with mixed property values

I am trying to update my app to use Swift 4 Decodable - and am pulling down data from a JSON api which has child values which could be:
A Child Object
A String
An Int
Here is the Json Api response:
var jsonoutput =
"""
{
"id": "124549",
"key": "TEST-32",
"fields": {
"lastViewed": "2018-02-17T21:40:38.864+0000",
"timeestimate": 26640
}
}
""".data(using: .utf8)
I have tried to parse it using the following: which works if I just reference the id and key properties which are both strings.
struct SupportDeskResponse: Decodable{
var id: String
var key: String
//var fields: [String: Any] //this is commented out as this approach doesn't work - just generated a decodable protocol error.
}
var myStruct: Any!
do {
myStruct = try JSONDecoder().decode(SupportDeskResponse.self, from: jsonoutput!)
} catch (let error) {
print(error)
}
print(myStruct)
How do I decode the fields object into my Struct?
You should create a new Struct adopting Decodable protocol like this :
struct FieldsResponse: Decodable {
var lastViewed: String
var timeestimate: Int
}
Then you can add it to your SupportDeskResponse
var fields: FieldsResponse