I'm new here. How to write and turn the code below into postString as I need to do submisson to API.
{
"service": 0,
"size": "string",
"orderReference": "string",
"dropOffHubId": "string",
"pickUpHubId": "string",
"courierId": "string",
"from": {
"address": {
"address1": "string",
"address2": "string",
"city": "string",
"postcode": "string",
"state": "string",
"country": "string"
}
},
"to": {
"name": "string",
"phone": "string",
"email": "string",
"address": {
"address1": "string",
"address2": "string",
"city": "string",
"postcode": "string",
"state": "string",
"country": "string"
}
}
}
Am I correct if I write it in this way, but how to put in the string after "from": { and also "address": { then go into "address1": "string", Then another one is "to": { "name": "string", then go inside
"address": {, then go inside "address1": "string",
let postString = [ "service": 0,
"size": "string",
"orderReference": "string",
"dropOffHubId": "string",
"pickUpHubId": "string",
"courierId": "string",
"from": "fromAddArr",
"to": "toAddArr"] as [String : Any]
var request = URLRequest(url:URL!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue(bearerToken!, forHTTPHeaderField: "Authorization")
request.httpBody = try! JSONSerialization.data(withJSONObject: postString, options:.prettyPrinted)
I only know to write in this way.
{
"refNo": "string",
"code": "string"
}
let postString = ["refNo": "string",
"code": "string"]
Try this one i think you want something like this : First take dictionary of address from current json and convert that dictionary into string :
let dictionary:[String:Any] = ["address": [
"address1": "string",
"address2": "string",
"city": "string",
"postcode": "string",
"state": "string",
"country": "string"
]
]
if let theJSONData = try? JSONSerialization.data( withJSONObject: dictionary, options: []) {
let theJSONText = String(data: theJSONData, encoding: .utf8)
print("JSON string = \(theJSONText!)") //you can use this string to create dictionary as you want
let dict = ["addres":theJSONText!]
print(dict)
}
You do not need to write that string by yourself. If you are using swift 3 and have a model class for that JSON string, you can use a third party lib here. This will convert your model into dictionary, array, json string and data etc. You just need to make your model child of ParsableModel or JSONParsable.
If you have problem in creating model class from JSON you can use this utility. This will generate model class for your JSON:
class RootClass {
var courierId: String?
var dropOffHubId: String?
var from: From?
var orderReference: String?
var pickUpHubId: String?
var service: NSNumber?
var size: String?
var to: To?
}
class To {
var address: Addres?
var email: String?
var name: String?
var phone: String?
}
class From {
var address: Addres?
}
class Addres {
var address1: String?
var address2: String?
var city: String?
var country: String?
var postcode: String?
var state: String?
}
If you are using Swift 4. It provides you classes to Encode and Decode your code from JSON to model and model to JSON. You can save your time by using this.
Related
I've created NSObject class for "CurrentUser",
here, sign-up API will call & response data will insert into the "CurrentUser" model.
This is one type of global model, like in any screen user_logic_details will fetch, modify & save.
Example :
let loginuser : CurrentUser = CurrentUser.getLoginData()!
loginuser.email = "abc#gmail.com"
CurrentUser.saveLoginData(loginData: loginuser)
// working
let email = CurrentUser.getLoginData()?.email ?? "" // i'll get "abc#gmail.com"
in the above example if I write the below code then it shows nil data
let loginuser : CurrentUser = CurrentUser.getLoginData()!
loginuser.email = "abc#gmail.com"
CurrentUser.saveLoginData(loginData: loginuser)
// working
let email = CurrentUser.getLoginData()?.email ?? "" // i'll get "abc#gmail.com"
// not working
let roleName = CurrentUser.getLoginData()?.roles?.name ?? "" // showing get ""
I'm not able to find exact issues here,
Check below the code of how I use the model class, saving data into UserDefaults & retrieve data from the model.
class CurrentUser: NSObject, NSCoding, NSKeyedUnarchiverDelegate {
var email : String!
var roles : UserRole!
private var _isLoggedIn = false
required convenience init(coder aDecoder: NSCoder) {
self.init()
roles = aDecoder.decodeObject(forKey: "roles") as? UserRole
email = aDecoder.decodeObject(forKey: "email") as? String
}
func encode(with aCoder: NSCoder) {
aCoder.encode(email, forKey: "email")
aCoder.encode(roles, forKey: "roles")
}
class func getLoginData() -> CurrentUser? {
let userDefaults = UserDefaults.standard
if let UserData = userDefaults.object(forKey: "loginUser") {
guard let unarchivedFavorites = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(UserData as! Data)
else {
return nil
}
return unarchivedFavorites as? CurrentUser
} else {
return CurrentUser()
}
}
class func saveLoginData(loginData: CurrentUser?) {
do {
let encodedData = try NSKeyedArchiver.archivedData(withRootObject: loginData as Any, requiringSecureCoding: false)
let userDefaults: UserDefaults = UserDefaults.standard
userDefaults.set(encodedData, forKey: "loginUser")
userDefaults.synchronize()
} catch {
print("Couldn't write file")
}
}
func unarchiver(_ unarchiver: NSKeyedUnarchiver, cannotDecodeObjectOfClassName name: String, originalClasses classNames: [String]) -> AnyClass? {
print("classNames", classNames)
return nil
}
}
class UserRole: NSObject, NSCoding {
var name : String!
required convenience init(coder aDecoder: NSCoder) {
self.init()
name = aDecoder.decodeObject(forKey: "name") as? String
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
}
}
The above model is for reference purposes.
I need to convert the below Response to the whole model class
{
"addressList": [
{
"addressLabel": "string",
"city": "string",
"country": "string",
"createdAt": "2022-03-16T12:10:41.148Z",
"homePhone": "string",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"isDefault": true,
"isDeleted": true,
"state": "string",
"streetAddress": "string",
"updatedAt": "2022-03-16T12:10:41.148Z",
"version": 0,
"zip": "string"
}
],
"ageRange": "string",
"badges": [
{
"badge": {
"createdAt": "2022-03-16T12:10:41.148Z",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"image": "string",
"isDeleted": true,
"label": "string",
"name": "string",
"status": "ACTIVE",
"updatedAt": "2022-03-16T12:10:41.148Z",
"users": [
null
],
"version": 0
},
"userBadgeId": {
"badgeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
}
],
"classesTaken": 0,
"createdAt": "2022-03-16T12:10:41.148Z",
"deviceList": [
{
"createdAt": "2022-03-16T12:10:41.148Z",
"deviceId": "string",
"deviceName": "string",
"deviceType": "ANDROID",
"display": "string",
"fcmToken": "string",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"isDeleted": true,
"osVersion": "string",
"updatedAt": "2022-03-16T12:10:41.148Z",
"version": 0
}
],
"displayName": "string",
"displayPic": "string",
"dob": "2022-03-16T12:10:41.148Z",
"email": "string",
"experience": 0,
"firebaseToken": "string",
"firebaseUserId": "string",
"followerCount0l": 0,
"fullName": "string",
"gender": "FEMALE",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"isDeleted": true,
"lastLoginTime": "2022-03-16T12:10:41.148Z",
"location": "string",
"phoneNumber": "string",
"roles": [
{
"createdAt": "2022-03-16T12:10:41.148Z",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"isDeleted": true,
"name": "ROLE_ADMIN",
"updatedAt": "2022-03-16T12:10:41.148Z",
"version": 0
}
],
"rubyBalance": 0,
"signupDateTime": "2022-03-16T12:10:41.148Z",
"signupSource": {
"buildNumber": "string",
"deviceId": "string",
"deviceType": "ANDROID",
"osVersion": "string"
},
"status": "ACTIVE",
"studentsTaught": 0,
"updatedAt": "2022-03-16T12:10:41.148Z",
"userInterest": [
"string"
],
"userName": "string",
"version": 0
}
If anyone has a better way to do it or a better solution, please answer it.
Your code reads like Objective-C from a few years ago. Something more modern and Swift-like might be:
#propertyWrapper
struct UserDefaultsCodableWrapper<T: Codable> {
let key: String
let defaultValue: T?
init(_ key: String, defaultValue: T?) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T? {
get {
guard let data = UserDefaults.standard.data(forKey: key),
let decoded = try? JSONDecoder().decode(T.self, from: data)
else { return defaultValue }
return decoded
}
set {
let encoded = try? JSONEncoder().encode(newValue)
UserDefaults.standard.set(encoded, forKey: key)
}
}
}
struct User: Codable {
var email: String // TODO make a codable "Email" struct type that validates its input, no invalid strings allowed
var roles: [UserRole]
}
struct UserRole: Codable {
var name: String
}
class AppState {
#UserDefaultsCodableWrapper("CurrentUser", defaultValue: nil)
var currentUser: User?
}
class ViewController: UIViewController {
let state = AppState()
override func viewDidLoad() {
super.viewDidLoad()
print(String(describing: state.currentUser)) // nil
state.currentUser = User(email: "foo#bar.baz", roles: [.init(name: "Foo"), .init(name: "Bar")])
print(String(describing: state.currentUser)) // Optional(User...
Also worth pointing you to app.quicktype.io which can generate you codable models from your json.
I have a codable struct like this
struct User: Codable {
let id: String
let registrationId: String
let firstName: String?
let lastName: String?
}
Now, the response from the server contains an array like this
[
{
"id": "1",
"registrationId": "r1",
"firstName": "Jon",
"lastName": "Doe"
},
{
"id": "2",
"registrationId": null,
"firstName": null,
"lastName": null
},
{
"id": "3",
"registrationId": null,
"firstName": null,
"lastName": null
},
{
"id": "4",
"registrationId": "r4",
"firstName": "Jon",
"lastName": "Snow"
}
]
I want to parse this as [User] but only those who have a valid(not null) registrationId. I know how to parse JSON in swift. But the problem here is because of the two invalid data in the middle the whole response will run into decoding error. But I want to parse it as an array of [User] containing valid ones(in this case first and last object).
Any hints or help is much appreciated.
1- Make registrationId an optional
let registrationId: String?
2-
let res = try JSONDecoder().decode([User].self,from:data)
let filtered = res.filter { $0.registrationId != nil }
after all, this data must come from a database or an array. By making the id parameter as the primary key, the registrationId parameter as a foreign key, and if you are working on the registrationId parameter, you can make a productive sequence or if it is on the array, you can link the method that generates the sequence for that registrationId.
Now I know how to achieve this.
struct User: Codable {
let id: String
let registrationId: String
let firstName: String?
let lastName: String?
}
struct WrappedDecodableArray<Element: Decodable>: Decodable {
let elements: [Element]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var elements = [Element]()
while !container.isAtEnd {
if let element = try? container.decode(Element.self) {
elements.append(element)
} else {
// move the container currentIndex forward
_ = try container.decode(Block.self)
}
}
self.elements = elements
}
private struct Block: Decodable {}
}
func testUserParsing() {
let jsonStr = """
[
{
"id": "1",
"registrationId": "r1",
"firstName": "Jon",
"lastName": "Doe"
},
{
"id": "2",
"registrationId": null,
"firstName": null,
"lastName": null
},
{
"id": "3",
"registrationId": null,
"firstName": null,
"lastName": null
},
{
"id": "4",
"registrationId": "r4",
"firstName": "Jon",
"lastName": "Snow"
}
]
"""
let jsonData = jsonStr.data(using: .utf8)!
let wrappedArray = try! JSONDecoder().decode(WrappedDecodableArray<User>.self, from: jsonData)
print(wrappedArray.elements)
}
It would have been more elegant if we could override the init(from decoder: Decoder) for Array under certain conditions like extension Array where Element == User. But looks like this is not possible. Initializer inside the extension can not override the original one and hence never get called.
So for now looks like wrapping with a struct is the only solution.
i am getting data from an api like this
[
{
"internData": {
"id": "abc123",
"name": "Doctor"
},
"author": "Will smith",
"description": "Is an actor",
"url": "https://www",
},
{
"internData": {
"id": "qwe900",
"name": "Constructor"
},
"author": "Edd Bett",
"description": "Is an Constructor",
"url": "https://www3",
}
]
I have my model like this
struct PersonData: Codable {
let author: String?
let description: String?
let url: String?
}
But I dont know how to define the "internData", I tried with another Model "InterData" and define id and name like the PersonData, but i get an error, i tried also with [String:Any] but i get an error for the Codable protocol
I am using
let resP = try JSONSerialization.jsonObject(with: data, options: .init()) as? [String: AnyObject]
print("resP", )
in my script of Service/Network
Thanks if somebody knows
You can't use [String:Any] type in case of Codable. you need to create an another model of InternData, which is used by PersonData.
Code:
JSON Data :
let jsonData =
"""
[
{
"internData": {
"id": "abc123",
"name": "Doctor"
},
"author": "Will smith",
"description": "Is an actor",
"url": "https://www",
},
{
"internData": {
"id": "qwe900",
"name": "Constructor"
},
"author": "Edd Bett",
"description": "Is an Constructor",
"url": "https://www3",
}
]
"""
// Models
struct PersonData: Codable {
let author: String?
let description: String?
let url: String?
let internData : InternData?
}
// New model
struct InternData : Codable {
let id : String?
let name : String?
}
// Parsing
do {
let parseRes = try JSONDecoder().decode([PersonData].self, from: Data(jsonData.utf8))
print(parseRes)
}
catch {
print(error)
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I want to get data from Json and put it in the table and display it from the API via Alamofire through the 'Post' process that has parameters containing the page number
I want get "results" ..
{
"responseCode": 200,
"message": null,
"status": true,
"results": [
{
"id": 971,
"title": "ST201972362",
"cdate": "07/31/2019",
"summary": "test",
"address": "",
"timer": "77876203",
"lat": "31.515934",
"lng": "34.4494066",
"source": "2",
"CreatedOn": "2019-07-31T13:38:46.927",
"done_940": null
},
{
"id": 970,
"title": "ST201972356",
"cdate": "07/30/2019",
"summary": "ov",
"address": "",
"timer": "0",
"lat": "31.5159315",
"lng": "34.4493925",
"source": "2",
"CreatedOn": "2019-07-30T15:26:00.077",
"done_940": null
},
{
"id": 964,
"title": "ST201972341",
"cdate": "07/29/2019",
"summary": "تجربة بلاغ ",
"address": "",
"timer": "0",
"lat": "21.5066086",
"lng": "39.1758587",
"source": "2",
"CreatedOn": "2019-07-29T19:06:58.817",
"done_940": null
},
{
"id": 959,
"title": "ST201972820252314",
"cdate": "07/28/2019",
"summary": "اااااا",
"address": "",
"timer": "0",
"lat": "21.5066716",
"lng": "39.1758483",
"source": "1",
"CreatedOn": "2019-07-28T11:45:02.493",
"done_940": null
},
{
"id": 957,
"title": "ST201972312",
"cdate": "07/28/2019",
"summary": "تمتمتم",
"address": "",
"timer": "0",
"lat": "31.5397884",
"lng": "34.4544891",
"source": "2",
"CreatedOn": "2019-07-28T08:56:43.577",
"done_940": null
},
{
"id": 956,
"title": "ST201972312",
"cdate": "07/28/2019",
"summary": "لا تنام",
"address": "",
"timer": "0",
"lat": "31.5397238",
"lng": "34.4540829",
"source": "2",
"CreatedOn": "2019-07-28T08:56:00.15",
"done_940": null
},
{
"id": 955,
"title": "ST201972311",
"cdate": "07/28/2019",
"summary": "تجربه جديد",
"address": "",
"timer": "0",
"lat": "31.5395001",
"lng": "34.4542211",
"source": "2",
"CreatedOn": "2019-07-28T08:52:09.81",
"done_940": null
},
{
"id": 953,
"title": "ST201972309",
"cdate": "07/28/2019",
"summary": "يلا",
"address": "",
"timer": "0",
"lat": "31.5110196",
"lng": "34.4784933",
"source": "2",
"CreatedOn": "2019-07-28T05:30:29.647",
"done_940": null
},
{
"id": 952,
"title": "ST201972309",
"cdate": "07/28/2019",
"summary": "ماك ١",
"address": "",
"timer": "0",
"lat": "31.5110291",
"lng": "34.4785841",
"source": "2",
"CreatedOn": "2019-07-28T05:29:09.943",
"done_940": null
},
{
"id": 949,
"title": "ST201972307",
"cdate": "07/28/2019",
"summary": "مرحبا",
"address": "",
"timer": "0",
"lat": "31.5443154",
"lng": "34.4585304",
"source": "2",
"CreatedOn": "2019-07-28T00:20:42.753",
"done_940": null
}
],
"done_940": "2/811"
}
You can follow some steps:
Step 1: need to create model
struct ResultObject {
var responseCode: Int?
var message: String?
var status: Bool?
var result: [Result]
public init(response: [String: Any]) {
self.responseCode = response["responseCode"] as? Int
self.message = response["message"] as? String
self.status = response["status"] as? Bool
let results = response["result"] as! [[String: Any]]
self.result = []
for item in results {
let result = Result(result: item)
self.result.append(result)
}
}
struct Result {
var id: String?
var title: String?
var cdate: String?
var summary: String?
var address: String?
var timer: String?
var lat: String?
var lng: String?
var source: String?
var CreatedOn: String?
var done_940: String?
public init(result: [String: Any]) {
self.id = result["id"] as? String
self.title = result["title"] as? String
self.cdate = result["cdate"] as? String
self.summary = result["summary"] as? String
self.address = result["address"] as? String
self.timer = result["timer"] as? String
self.lat = result["lat"] as? String
self.lng = result["lng"] as? String
self.source = result["source"] as? String
self.CreatedOn = result["CreatedOn"] as? String
self.done_940 = result["done_940"] as? String
}
}
}
Step 2: You check response from Alamofile
if you get json then
let test = ResultObject(response: responseJson)
print(test)
incase you get response is type Response you must convert into json
let responseJSON = try? JSONSerialization.jsonObject(with: response.data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
let test = ResultObject(response: responseJSON)
print(test)
}
Let me know when you have some other problems.
To parse a JSON, as I found also on the web, I usually used this kind of code:
guard let results = receivedUserJSON["results"] as? [String: Any] else {
print("Error interpreting results")
return
}
This time I have a problem, because it seems to end in the else of this guard let. The JSON has the following structure:
{
"results": [{
"gender": "female",
"name": {
"title": "mrs",
"first": "silene",
"last": "almeida"
},
"location": {
"street": "2594 rua maranhão ",
"city": "pouso alegre",
"state": "distrito federal",
"postcode": 20447,
"coordinates": {
"latitude": "-70.0198",
"longitude": "123.6577"
},
"timezone": {
"offset": "+4:30",
"description": "Kabul"
}
},
"email": "silene.almeida#example.com",
"login": {
"uuid": "d06a46b3-1c00-42be-b8fc-d271bf901f7d",
"username": "silversnake251",
"password": "ventura",
"salt": "UcckU6RG",
"md5": "7c8c4129587c61da01ca7cf4f88353c5",
"sha1": "6cbf7ec377ff4ebad5a392ec487343bf613858ef",
"sha256": "8dedf3649fb833a1936b8885627b86c6cf02062eb74f727b2cbd674a30f73e75"
},
"dob": {
"date": "1969-07-13T00:58:26Z",
"age": 49
},
"registered": {
"date": "2003-09-28T09:44:56Z",
"age": 15
},
"phone": "(95) 0094-8716",
"cell": "(20) 1014-3529",
"id": {
"name": "",
"value": null
},
"picture": {
"large": "https://randomuser.me/api/portraits/women/66.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/66.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/66.jpg"
},
"nat": "BR"
}],
"info": {
"seed": "dd971cddf636d2d7",
"results": 1,
"page": 1,
"version": "1.2"
}
}
What should I do to properly parse this JSON? I would prefer not to go for the Codable solution because I don't need all of these values.
PS: I know the json is correct because I tried and printed it with:
if let JSONString = String(data: responseData, encoding: String.Encoding.utf8) {
print(JSONString)
}
results is an array
guard let results = receivedUserJSON["results"] as? [[String:Any]] else {
print("Error interpreting results")
return
}
I see no value for it to be an array as it contains 1 element so you may think to alter this json
current strucsture
{
"results": [{}],
"info": {
"seed": "dd971cddf636d2d7",
"results": 1,
"page": 1,
"version": "1.2"
}
}
you may alter it to
{
"results": {},
"info": {
"seed": "dd971cddf636d2d7",
"results": 1,
"page": 1,
"version": "1.2"
}
}