0

i working on project where i have to receive data from php server. Everything works good, only two things: 1.) can't parse Date. I know that this question was answered here, but not one of the variants is working in my case. Here is my code

import Foundation
import SwiftyJSON


func getClientDataFromServer(id: String?) {
    guard let id = id else {return}
    let jsonUrlString = "https://sverlim.software/cms/clientReadOneClient.php?client_id=10"
    let url = URL(string: jsonUrlString)!
    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard err == nil else {
            print(err!.localizedDescription)
            return
        }
        print(response as Any)
        guard let data = data else {return}
        let dateFormatterWithTime: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        formatter.timeZone = TimeZone(abbreviation: "UTC")
        formatter.locale = Locale(identifier: "en_US_POSIX")
        return formatter
        }()

        let datastring = String(data: data, encoding: .utf8)
        print("data====\(datastring!)")
        let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [[String:Any]]
        print(json[0]["datarteg"] as Any)
        do {
            let decoder = JSONDecoder()

            let object = try! JSON(data: data)
            print(object[0]["datareg"].dateTime)
            print(object[0]["company"].stringValue)

            decoder.dateDecodingStrategy = .formatted(dateFormatterWithTime)
            let clients = try decoder.decode([Client].self, from: data)
            print(clients)
            let client = clients.first
            print(client!)
        } catch let jsonErr {
            print(jsonErr)
        }
        }.resume()
}
struct Client: Codable {
    let id: String?
    let name: String?
    let phone: String?
    let company: String?
    let discount: String?
    var datareg: Date?
}

class Formatter {
    static let jsonDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()

    static let jsonDateTimeFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss"
        return formatter
    }()
}

extension JSON {

    public var date: Date? {
        get {
            switch self.type {
            case .string:
                return Formatter.jsonDateFormatter.date(from: self.object as! String)
            default:
                return nil
            }
        }
    }

    public var dateTime: Date? {
        get {
            switch self.type {
            case .string:
                return Formatter.jsonDateTimeFormatter.date(from: self.object as! String)
            default:
                return nil
            }
        }
}

i followed this answers

Swift's JSONDecoder with multiple date formats in a JSON string?

How do I format JSON Date String with Swift?

https://useyourloaf.com/blog/swift-codable-with-custom-dates/

here is what i'm printing from log

data====
 [{"id":"10","name":"\u0423\u043a\u0440\u0430\u0438\u043d\u0435\u0446 
 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440","phone":"+38098497
 4673","company":"2","discount":"0","datereg":"2017-11-28 14:16:16"}]
 nil
 nil
 2
 [SashaApp.Client(id: Optional("10"), name: Optional("Украинец Александр"), 
 phone: Optional("+380984974673"), company: Optional("2"), discount: 
 Optional("0"), datareg: nil)]
 Client(id: Optional("10"), name: Optional("Украинец Александр"), phone: 
 Optional("+380984974673"), company: Optional("2"), discount: 
 Optional("0"), datareg: nil)

As we can see the data contains "datareg" field, but after parsing regardless the way(JSONDecoder,JSONSerialization,SwiftyJSON) i receive nil 2) SSL_ERROR_ZERO_RETURN(6)

Guys will be appreciate for any help. Thank's))

Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90

2 Answers2

0

There are two ways to parsing a JSON.

Before Swift 4

Before Swift 4 you could only use JSONSerialization Class (like in your example). This method return a Any object that can be cast in a Dictionary (the type depends on the data you are receiving).

For example:

if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String,String>{
   do some stuff...
}

If you have multiple kind of data you should use this casting:

if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String,Any?>{
       do some stuff...
}

Then you can access to all the data in the dictionary by the key and manage the data (if you use Any remember to cast in the correct data before using them).

Here some documentation: https://developer.apple.com/documentation/foundation/jsonserialization

After Swift 4

With Swift 4 a new class was introduced: JSONEncoder and JSONDecoder. It's amazing, because you can create your model, parsing the json and you'll get an object with all the fields already filled. Pay attention that your model MUST implements the protocol Codable (or Encodable and Decodable). If your model doesn't implements the protocol you'll get an error.

Here an example:

This is my model:

class myClass: Codable{
    var Id: Int
    var Identifier: String
    var Alias: String
    var Revision: Int
    var Title: String
}

And this is the code for the parsing:

let decoder = JSONDecoder()

let myClass = try! decoder.decode(Questionario.self, from: (json?.data(using: .utf8))!)

Now my variable "myClass" already contains all the field filled with the data in the json.

Here some documentation:

https://developer.apple.com/documentation/swift/codable

https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

Fab
  • 816
  • 8
  • 17
  • Thank's a lot , but i was testing JSONSerializator and JSONDecoder and also tried SwiftyJSON as you see above, and in every case i see that with data from server "datareg" field coming with date, but after parsing i receive nil( – Anton Zhevchenko Jan 26 '18 at 14:43
  • Can you show me the dataString when you download it? You have the problem only in that field? – Fab Jan 26 '18 at 14:51
0

You have a typo in your text:

print(object[0]["datareg"].dateTime)

should be

print(object[0]["datereg"].dateTime)
Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90