In my case I am trying to get JSON data using codable. Here, I can’t able to get data[Datum] values. How to get it and assign tableview data. I used to generate codable by using quicktype.io
JSON Data
{
"status": true,
"data": [
{
"id": "1",
"name": "one",
"description": "hello",
"date": "2020-08-05 11:37:52",
"startdate": "2019-08-05 11:37:52",
"createdby": "1",
"status": "0"
},
{
"id": "2",
"name": "two",
"description": "hi",
"date": "2020-08-05 11:37:52",
"startdate": "2019-08-05 11:37:52",
"createdby": "1",
"status": "0"
}
]
}
Codable Struct
// MARK: - Welcome
struct Welcome: Codable {
let status: Bool
let data: [Datum]
}
// MARK: - Datum
struct Datum: Codable {
let id, name, datumDescription, date: String
let startdate, createdby, status: String
enum CodingKeys: String, CodingKey {
case id, name
case datumDescription = "description"
case date, startdate, createdby, status
}
}
Code
let id: String = result.data.(Nothing Showing except Description)
let id: String = result.data.(Nothing Showing except Description)
It's not clear what "Nothing Showing except Description" means here, but the syntax you would expect would be:
let id: String = result.data[0].id // The id of the first Datum
data is an Array, so you'll need to subscript or iterate over it to get elements. For a tableview, you'd expect something like:
let id: String = result.data[indexPath.row].id
If this is not what you mean, you need to edit your question to make clear what your actual code is and the specific error message you receive.
Related
I am building an app that lets users search for photos. I am in the process of creating a data model using a codable. Below is the JSON data. The data model will contain id, created_at, username, name, portfolio_url, and images. How do I access the nested user and image information in the user dictionary and URL images.
{
"id": "LBI7cgq3pbM",
"created_at": "2016-05-03T11:00:28-04:00",
"updated_at": "2016-07-10T11:00:01-05:00",
"width": 5245,
"height": 3497,
"color": "#60544D",
"blur_hash": "LoC%a7IoIVxZ_NM|M{s:%hRjWAo0",
"likes": 12,
"liked_by_user": false,
"description": "A man drinking a coffee.",
"user": {
"id": "pXhwzz1JtQU",
"username": "poorkane",
"name": "Gilbert Kane",
"portfolio_url": "https://theylooklikeeggsorsomething.com/",
"bio": "XO",
"location": "Way out there",
"total_likes": 5,
"total_photos": 74,
"total_collections": 52,
"instagram_username": "instantgrammer",
"twitter_username": "crew",
"
},
"urls": {
"raw": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
"full": "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
"regular": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
"small": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
"thumb": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef"
},
When using Codable you need to follow the hierarchy of the model.
Use three structs or classes as:
struct URLs: Codable {
var raw: String
var full: String
var regular: String
var small: String
var thumb: String
}
struct User: Codable {
var id: String
var name: String
var portfolio_url: String
var bio: String
}
struct DataModel: Codable {
var id: String
var created_at: String
var likes: Int
var liked_by_user: Bool
var description: String
var urls: URLs
var user: User
}
When decoding, just user
jsonDecoder.decode(DataModel.self, from: data)
I have JSON that looks like:
[
{
WWW: "2",
XXX: "2",
YYY: "3",
ZZZ: "4"
},
{
WWW: "2",
XXX: "5",
YYY: "6",
ZZZ: "7"
},
{
WWW: "2",
XXX: "2",
YYY: "2",
ZZZ: "3"
}
]
But I'm only interested in working with and Y and Z.
Howe can I remove the entire W and X columns either from the raw JSON or from the JSON in the form of an Array in SWIFT?
Only answers I can find such as here seem outdated. Thanks for suggestions.
Use:
dict["WWW"] = nil
dict["XXX"] = nil
or:
dict.removeValue(forKey: "WWW")
dict.removeValue(forKey: "XXX")
Better Approach would be using JSONEncoder and CodingKeys.
struct Model: Decodable {
var yyy, zzz: String
enum CodingKeys: String, CodingKey {
case yyy = "YYY", zzz = "ZZZ"
}
}
Define your struct to match what you want, and then decode it:
struct Value: Decodable {
enum CodingKeys: String, CodingKey {
case y = "YYY"
case z = "ZZZ"
}
var y: String
var z: String
}
let value = try JSONDecoder().decode([Value].self, from: json)
This will exclude any keys you don't include.
Currently, I'm trying to use Swift's codable protocol to add and read custom objects to and from Firebase's database. I've been following the instructions in these docs. However, when I try to write to the database, I'm getting an error "FIRInvalidArgumentException: Nested arrays are not supported". But aren't they supported? I saw another post on here from a couple of years ago that addressed a similar issue but I don't understand what I did wrong here.
These are the Swift struct representations that implement Codable:
struct List: Codable {
var title: String
var date: String
var description: String
var data: [SectionHeaders: Array<Item>] = [
.produce: [],
.seafood: [],
.meat: [],
.deli: [],
.bakery: [],
.pantry: [],
.dairy: [],
.frozen: [],
.other: []
]
enum CodingKeys: String, CodingKey {
case name
case date
case description
case data = "items"
}
struct Item: Codable {
var name: String?
var quantity: String?
}
enum SectionHeaders: Int, Codable {
case produce = 0, seafood, meat, deli, bakery, pantry, dairy, frozen, other, total
enum CodingKeys: String, CodingKey {
case produce = "produce"
case seafood = "seafood"
case meat = "meat"
case deli = "deli"
case bakery = "bakery"
case pantry = "pantry"
case dairy = "dairy"
case frozen = "frozen"
case other = "other"
}
}
And this is the data representation I'm aiming to get:
"title": String,
"date": String,
"description": String,
"items": [
"header1": [{
"name": String,
"quantity": String
},
{
"name": String,
"quantity": String
}
],
"header2": [{
"name": String,
"quantity": String
},
{
"name": String,
"quantity": String
}
]
]
Any help would be great! Thanks in advance!
This is my api response:
[
[
{
"id": 24,
"request_id": "rqst5c130cae6f7609.41056231",
"business_name": "Code Viable",
"business_email": "code#viable.com",
"title": "Load",
"details": "load",
"load_description": "load",
"amount_offered": "1",
"pickup_address": "load",
"dropoff_address": "load",
"timestamp": "2018-12-14 01:51:42"
}
],
[
{
"id": 27,
"request_id": "rqst5c1325881836d2.98441728",
"business_name": "Code Viable",
"business_email": "code#viable.com",
"title": "Load",
"details": "brendan",
"load_description": "test load for brendan",
"amount_offered": "1222",
"pickup_address": "Load",
"dropoff_address": "Load",
"timestamp": "2018-12-14 03:37:44"
}
]
]
As you can see, it is an array wrapped inside of an array, I have an object mapper setup already for the inner array, like this:
struct JobResponseDataObject: Mappable {
init?(map: Map) {
}
var id: Int?
var requestId: String?
var businessName: String?
var businessEmail: String?
var title: String?
var details: String?
var loadDescription: String?
var amountOffered: String?
var pickUpAddress: String?
var dropOffAddress: String?
var timestamp: String?
mutating func mapping(map: Map) {
id <- map["id"]
requestId <- map["request_id"]
businessName <- map["business_name"]
businessEmail <- map["business_email"]
title <- map["title"]
details <- map["details"]
loadDescription <- map["load_description"]
amountOffered <- map["amount_offered"]
pickUpAddress <- map["pickup_address"]
dropOffAddress <- map["dropoff_address"]
timestamp <- map["timestamp"]
}
}
If the parent has a name for it's child array, then I would create another mapper for the top level. But in this case, there is not a name for the outer array, what do I need to do to make the alamofire .responseArray call work?
Alamofire.request(JOB_REQUEST_BASE_URL, method: .post, parameters: parameter, encoding: URLEncoding(), headers: nil).responseArray { (response: DataResponse<[JobResponseDataObject]>) in
}
}
Thanks
Your JSON object have nested Array. So to parse that you can do it two ways. One way to do this is to parse it as nested array.
DataResponse<[[JobResponseDataObject]]>
And your code will looks like this.
Alamofire.request(JOB_REQUEST_BASE_URL, method: .post, parameters: parameter, encoding: URLEncoding(), headers: nil).responseArray { (response: DataResponse<[JobResponseDataObject]>) in
//...
}
Suggestion: So far what I can understand from JSON, it should not be in nested Array. If you only need to add one object in nested array, you can achieve same with simple array.
Second Way
If you only have one object in nested array. You can also parse it as following.
requestId <- map["0.request_id"]
"0." is here to get first object of inner array.
Hope this helps :)
I want to get "key of dictionary" (that's what I called, not sure if it is right name) on this JSON
{
"People": {
"People with nice hair": {
"name": "Peter John",
"age": 12,
"books": [
{
"title": "Breaking Bad",
"release": "2011"
},
{
"title": "Twilight",
"release": "2012"
},
{
"title": "Gone Wild",
"release": "2013"
}
]
},
"People with jacket": {
"name": "Jason Bourne",
"age": 15,
"books": [
{
"title": "Breaking Bad",
"release": "2011"
},
{
"title": "Twilight",
"release": "2012"
},
{
"title": "Gone Wild",
"release": "2013"
}
]
}
}
}
First of all, I already created my People struct that will be used to map from those JSON.
Here is my people struct
struct People {
var peopleLooks:String?
var name:String?
var books = [Book]()
}
And here is my Book struct
struct Book {
var title:String?
var release:String?
}
From that JSON, I created engine with Alamofire and SwiftyJSON that will be called in my controller via completion handler
Alamofire.request(request).responseJSON { response in
if response.result.error == nil {
let json = JSON(response.result.value!)
success(json)
}
}
And here is what I do in my controller
Engine.instance.getPeople(request, success:(JSON?)->void),
success:{ (json) in
// getting all the json object
let jsonRecieve = JSON((json?.dictionaryObject)!)
// get list of people
let peoples = jsonRecieve["People"]
// from here, we try to map people into our struct that I don't know how.
}
My question is, how to map my peoples from jsonRecieve["People"] into my struct?
I want "People with nice hair" as a value of peopleLooks on my People struct. I thought "People with nice hair" is kind of key of dictionary or something, but I don't know how to get that.
Any help would be appreciated. Thank you!
While you iterate through dictionaries, for instance
for peeps in peoples
You can access key with
peeps.0
and value with
peeps.1
You can use key, value loop.
for (key,subJson):(String, JSON) in json["People"] {
// you can use key and subJson here.
}