简体   繁体   English

iOS 错误“JSON 写入 (FIRTimestamp) 中的类型无效”

[英]iOS error 'Invalid type in JSON write (FIRTimestamp)'

I am trying to map my data to Model. Where I am using Firestore snapshot listener, to get data.我正在尝试将我的数据 map 转换为 Model。我在其中使用 Firestore 快照侦听器来获取数据。 here, I am getting data and mapping to "User" model that;在这里,我正在获取数据并将其映射到“用户”model

            do{
                let user = try User(dictionary: tempUserDic)
                print("\(user.firstName)")
            }
            catch{
                print("error occurred")
            }

Here is my Model:这是我的Model:

struct User {
    let firstName: String
//    var lon: Double = 0.0
//    var refresh:Int = 0
//    var createdOn: Timestamp = Timestamp()
}

//Testing Codable
extension User: Codable {
    init(dictionary: [String: Any]) throws {
        self = try JSONDecoder().decode(User.self, from: JSONSerialization.data(withJSONObject: dictionary))
    }
    private enum CodingKeys: String, CodingKey {
        case firstName = "firstName"
    }
}

Correct me if I am wrong.如果我错了,请纠正我。

Crashing because I am getting "Timestamp" in data.崩溃是因为我在数据中得到“时间戳”。

Data getting from listener:从侦听器获取的数据:

User Dictionary :用户词典

[\"firstName\": Ruchira,
 \"lastInteraction\": FIRTimestamp: seconds=1576566738 nanoseconds=846000000>]"

How to map "Timestamp" to Model?如何将 map“时间戳”转换为 Model?

Tried "CodableFirstore" https://github.com/alickbass/CodableFirebase试过“CodableFirstore” https://github.com/alickbass/CodableFirebase

I solved this by converting the FIRTimestamp fields to Double (seconds) so the JSONSerialization could parse it accordingly.我通过将FIRTimestamp字段转换为Double (秒)来解决这个问题,因此JSONSerialization可以相应地解析它。

 let items: [T] = documents.compactMap { query in
   var data = query.data() // get a copy of the data to be modified.

   // If any of the fields value is a `FIRTimestamp` we replace it for a `Double`.
   if let index = (data.keys.firstIndex{ data[$0] is FIRTimestamp }) {

     // Convert the field to `Timestamp`
     let timestamp: Timestamp = data[data.keys[index]] as! Timestamp

     // Get the seconds of it and replace it on the `copy` of `data`.
     data[data.keys[index]] = timestamp.seconds

    }

    // This should not complain anymore.
    guard let data = try? JSONSerialization.data(
       withJSONObject: data, 
       options: .prettyPrinted
    ) else { return nil }

    // Make sure your decoder setups the decoding strategy to `. secondsSince1970` (see timestamp.seconds documentation).
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .secondsSince1970
    return try? decoder.decode(T.self, from: data)
 }

// Use now your beautiful `items`
return .success(items)

An approach is to create an extension to type Dictionary that coverts a dictionary to any other type, but automatically modifies Date and Timestamp types to writeable JSON strings.一种方法是创建类型Dictionary的扩展,将字典转换为任何其他类型,但自动将DateTimestamp类型修改为可写的 JSON 字符串。

This is the code:这是代码:

extension Dictionary {

    func decodeTo<T>(_ type: T.Type) -> T? where T: Decodable {
        
        var dict = self

        // This block will change any Date and Timestamp type to Strings
        dict.filter {
            $0.value is Date || $0.value is Timestamp
        }.forEach {
            if $0.value is Date {
                let date = $0.value as? Date ?? Date()
                dict[$0.key] = date.timestampString as? Value
            } else if $0.value is Timestamp {
                let date = $0.value as? Timestamp ?? Timestamp()
                dict[$0.key] = date.dateValue().timestampString as? Value
            }
        }

        let jsonData = (try? JSONSerialization.data(withJSONObject: dict, options: [])) ?? nil
        if let jsonData {
            return (try? JSONDecoder().decode(type, from: jsonData)) ?? nil
        } else {
            return nil
        }
    }
}

The .timestampString method is an also declared in an extension for type Date : .timestampString方法也在Date类型的扩展中声明:

extension Date {
    
    var timestampString: String {
        Date.timestampFormatter.string(from: self)
    }
    
    static private var timestampFormatter: DateFormatter {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        dateFormatter.timeZone = TimeZone(identifier: "UTC")
        return dateFormatter
    }
}

Usage, like in the case of the question:用法,就像问题的情况一样:

let user = tempUserDic.decodeTo(User.self)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法将“FIRTimestamp”类型的值转换为“FIRTimestamp” - Could not cast value of type 'FIRTimestamp' to 'FIRTimestamp' Firestore 写入文档 numpy 的无效类型错误 - Firestore write to document invalid type errors for numpy Azure Databricks 写入 JSON 数据到 Parquet 文件抛出错误:TypeError:无法推断类型的模式 - Azure Databricks write JSON Data to Parquet file throws error: TypeError: Can not infer schema for type 使用 Firebase 匿名身份验证,错误,JSON 无效 - Using Firebase Anonymous Authentication, error, invalid JSON AWS Sagemaker 错误 INVALID_INFERENCE_TYPE - AWS Sagemaker error INVALID_INFERENCE_TYPE Redshift - 错误:数字类型的输入语法无效 - Redshift - ERROR: Invalid input syntax for type numeric 如何解决 iOS 的 ANH 中的无效凭据错误? - How to resolved Invalid Credential error in ANH for iOS? 表单识别器自定义 model 失败,文件类型无效 `{"error":{"code":"1000","message":"Invalid input file."}}` - Form Recognizer custom model fails with invalid file type `{"error":{"code":"1000","message":"Invalid input file."}}` 错误:HTTP 错误:400,收到无效的 JSON 有效载荷。 未知名称“skipLog”:找不到字段 - Error: HTTP Error: 400, Invalid JSON payload received. Unknown name "skipLog": Cannot find field 类型 json aws dms postgres 的无效输入语法 - invalid input syntax for type json aws dms postgres
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM