Swift:从 JSON 解析日期 [关闭]

Posted

技术标签:

【中文标题】Swift:从 JSON 解析日期 [关闭]【英文标题】:Swift: parsing Date from JSON [closed] 【发布时间】:2018-01-26 14:29:31 【问题描述】:

我正在处理我必须从 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
            
        

我遵循了这个答案

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/

这是我从日志中打印的内容

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)

如果您能提供任何帮助,我们将不胜感激。谢谢))

【问题讨论】:

你的代码会发生什么?在解析之前打印出日期字符串,并将其包含在此处,以便我们确认您使用的格式正确 我打印它是因为我想查看我从服务器接收到的数据。 无需转义日期分隔符 "yyyy-MM-dd HH:mm:ss" 并确保将时区设置为 UTC 并将您的区域设置为 "en_US_POSIX" 您的日期格式缺少时区 所以只需将 "datareg" 更改为 "datereg" 就可以了 【参考方案1】:

您的文字中有错字:

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

应该是

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

【讨论】:

这将是关闭主题的原因(简单的印刷错误) 我发布了所有功能,以便任何有兴趣帮助的人可以使用来重现我的问题) @AntonZhevchenko 这不是你的问题的原因吗? 是的,使用 SwiftyJSON)) 是的,你解决了我的问题))谢谢【参考方案2】:

解析 JSON 有两种方法。

在 Swift 4 之前

在 Swift 4 之前,您只能使用 JSONSerialization 类(如您的示例中所示)。此方法返回一个可以在 Dictionary 中强制转换的 Any 对象(类型取决于您接收的数据)。

例如:

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...

然后您可以通过键访问字典中的所有数据并管理数据(如果您使用 Any 记得在使用它们之前输入正确的数据)。

这里有一些文档:https://developer.apple.com/documentation/foundation/jsonserialization

在 Swift 4 之后

在 Swift 4 中引入了一个新类:JSONEncoder 和 JSONDecoder。太棒了,因为您可以创建模型,解析 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中的数据填充的字段。

这里有一些文档:

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

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

【讨论】:

非常感谢,但我正在测试 JSONSerializator 和 JSONDecoder 并且还尝试了 SwiftyJSON,如您在上面看到的,并且在每种情况下,我都看到来自服务器“datareg”字段的数据带有日期,但在解析之后我收到零( 你下载的时候能给我看看dataString吗?你只在那个领域有问题?

以上是关于Swift:从 JSON 解析日期 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Swift 使用 Alamofire 和 SwiftyJSON 解析 Json [关闭]

Swift 中的特殊 JSON 解析 [关闭]

在 Swift 中解析 JSON 24 小时的问题 [关闭]

如何使用 Swift 的 Decodable 解析任意 JSON 字符串,而您只知道或关心几个字段? [关闭]

如何从模型数据 Swift 创建 JSON 字符串? [关闭]

iOS如何从解析Swift 4中获取行[关闭]