How to remove properties (key:values) from JSON object in Swift - ios

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.

Related

How to Build a custom data model for search query and user detail using Unlash Api?

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)

FIRInvalidArgumentException: Nested arrays are not supported

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!

Swift Codable not working for array of values

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.

filter array of json in swift

How can i filter an array of json in swift having only certain key value pairs?
my array looks like:
[{
"status" : "true",
"score" : "3",
"correct" : "3",
"chapter" : "34",
"answer" : "342432",
"solutionText" : "abcd",
}, {
"status" : "true",
"score" : "0",
"correct" : "2",
"chapter" : "35",
"answer" : "35854",
"solutionText" : "abc",
}]
i want to get an array of json output having only status, chapter & correct key value pairs.
Like:
[{
"status" : "true",
"correct" : "3",
"chapter" : "34",
}, {
"status" : "true",
"correct" : "2",
"chapter" : "35",
}]
Considering this is your JSON
var myJSON = """
[{
"status" : "true",
"score" : "3",
"correct" : "3",
"chapter" : "34",
"answer" : "342432",
"solutionText" : "abcd"
}, {
"status" : "true",
"score" : "0",
"correct" : "2",
"chapter" : "35",
"answer" : "35854",
"solutionText" : "abc"
}]
"""
Simply create a Decodable struct like this
typealias MyArray = [MyObject] // Use this to decode
struct MyObject: Codable {
let status, correct, chapter: String
}
And use it like this
//Usage
var myJSONData = myJSON.data(using: .utf8)! // converting the JSON to data
let objArray = try! JSONDecoder().decode(MyArray.self, from: myJSONData) // decoding the json data into an object
//how to access
print(objArray.count)// number of elements in my array
print(objArray.first!) // getting the first object
let myObject = obj[0] // also getting the first object by index
myObject.chapter
myObject.correct
myObject.status
Read about Codable here .
If it's already in an object, you can try
filteredArray = myArray.map { ["status": $0.status, "correct": $0.correct, "chapter": $0.chapter] }
You can try
do {
let res = try JSONDecoder().decode([Root].self, from:data)
}
catch {
print(error)
}
struct Root: Codable {
let status, correct, chapter: String
}
Correct json
[{
"status" : "true",
"score" : "3",
"correct" : "3",
"chapter" : "34",
"answer" : "342432",
"solutionText" : "abcd"
}, {
"status" : "true",
"score" : "0",
"correct" : "2",
"chapter" : "35",
"answer" : "35854",
"solutionText" : "abc"
}]
It's more suitable to make
status a bool not string
correct & chapter to be integers
so json look like
[{
"status" : true,
"score" : "3",
"correct" : 3,
"chapter" : 34,
"answer" : "342432",
"solutionText" : "abcd"
}, {
"status" : true,
"score" : "0",
"correct" : 2,
"chapter" : 35,
"answer" : "35854",
"solutionText" : "abc"
}]
you can also make other values like that if you need , then your model will look like
struct Root: Codable {
let status: Bool
let correct, chapter: Int
}
Edit:
let data = try content.rawData() // this inside do block
where content is of type JSON
try Decodable of swift
class MyObjectsClass : Decodable {
var objects : [Objects]?
}
class Objects : Decodable {
var status : String?
var correct : String?
var chapter : String?
}
While Decoding
let decodedValue = try? JSONDecoder.decode(MyObjectsClass.self, from : data)
// where data from API calls

Alamofire object mapper: how to parse nested array in swift

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 :)

Resources