Swift: 从 JSON 解析日期
Swift: parsing Date from JSON
我正在做一个项目,我必须从 php 服务器接收数据。一切正常,只有两件事:
1.) 无法解析日期。我知道这个问题在这里得到了回答,但没有一个变体适用于我的情况。这是我的代码
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
}
}
}
我遵循了这个答案
https://useyourloaf.com/blog/swift-codable-with-custom-dates/
这是我从日志中打印的内容
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)
正如我们所见,数据包含 "datareg" 字段,但无论采用何种方式(JSONDecoder、JSONSerialization、SwiftyJSON)进行解析后,我都收到 nil
2) SSL_ERROR_ZERO_RETURN(6)
大家将不胜感激。谢谢))
解析JSON有两种方法。
之前 Swift 4
在 Swift 4 之前,您只能使用 JSONSerialization Class(就像在您的示例中一样)。此方法 return 可以在字典中转换的任何对象(类型取决于您接收的数据)。
例如:
if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String,String>{
do some stuff...
}
如果您有多种类型的数据,您应该使用此转换:
if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String,Any?>{
do some stuff...
}
然后你就可以通过key访问字典中的所有数据并管理数据(如果你使用Any记得在使用它们之前输入正确的数据)
这里是一些文档:https://developer.apple.com/documentation/foundation/jsonserialization
Swift4
之后
随着 Swift 4 引入了一个新的 class:JSON编码器和 JSON解码器。这太棒了,因为您可以创建模型,解析 json 并且您将获得一个已填充所有字段的对象。请注意,您的模型必须实现协议 Codable(或 Encodable 和 Decodable)。如果您的模型未实现协议,您将收到错误消息。
举个例子:
这是我的模型:
class myClass: Codable{
var Id: Int
var Identifier: String
var Alias: String
var Revision: Int
var Title: String
}
这是解析代码:
let decoder = JSONDecoder()
let myClass = try! decoder.decode(Questionario.self, from: (json?.data(using: .utf8))!)
现在我的变量 "myClass" 已经包含了 json 中填充数据的所有字段。
这里是一些文档:
您的文字有误:
print(object[0]["datareg"].dateTime)
应该是
print(object[0]["datereg"].dateTime)
我正在做一个项目,我必须从 php 服务器接收数据。一切正常,只有两件事: 1.) 无法解析日期。我知道这个问题在这里得到了回答,但没有一个变体适用于我的情况。这是我的代码
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
}
}
}
我遵循了这个答案
https://useyourloaf.com/blog/swift-codable-with-custom-dates/
这是我从日志中打印的内容
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)
正如我们所见,数据包含 "datareg" 字段,但无论采用何种方式(JSONDecoder、JSONSerialization、SwiftyJSON)进行解析后,我都收到 nil 2) SSL_ERROR_ZERO_RETURN(6)
大家将不胜感激。谢谢))
解析JSON有两种方法。
之前 Swift 4
在 Swift 4 之前,您只能使用 JSONSerialization Class(就像在您的示例中一样)。此方法 return 可以在字典中转换的任何对象(类型取决于您接收的数据)。
例如:
if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String,String>{
do some stuff...
}
如果您有多种类型的数据,您应该使用此转换:
if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String,Any?>{
do some stuff...
}
然后你就可以通过key访问字典中的所有数据并管理数据(如果你使用Any记得在使用它们之前输入正确的数据)
这里是一些文档:https://developer.apple.com/documentation/foundation/jsonserialization
Swift4
之后随着 Swift 4 引入了一个新的 class:JSON编码器和 JSON解码器。这太棒了,因为您可以创建模型,解析 json 并且您将获得一个已填充所有字段的对象。请注意,您的模型必须实现协议 Codable(或 Encodable 和 Decodable)。如果您的模型未实现协议,您将收到错误消息。
举个例子:
这是我的模型:
class myClass: Codable{
var Id: Int
var Identifier: String
var Alias: String
var Revision: Int
var Title: String
}
这是解析代码:
let decoder = JSONDecoder()
let myClass = try! decoder.decode(Questionario.self, from: (json?.data(using: .utf8))!)
现在我的变量 "myClass" 已经包含了 json 中填充数据的所有字段。
这里是一些文档:
您的文字有误:
print(object[0]["datareg"].dateTime)
应该是
print(object[0]["datereg"].dateTime)