当前位置: 首页 > 面试题库 >

Swift 4 JSON Decodable解码类型更改的最简单方法

赵雅懿
2023-03-14
问题内容

借助Swift 4的Codable协议,可以很好地了解标准日期和数据转换策略。

鉴于JSON:

{
    "name": "Bob",
    "age": 25,
    "tax_rate": "4.25"
}

我想将其强制为以下结构

struct ExampleJson: Decodable {
    var name: String
    var age: Int
    var taxRate: Float

    enum CodingKeys: String, CodingKey {
       case name, age 
       case taxRate = "tax_rate"
    }
}

日期解码策略可以将基于字符串的日期转换为日期。

有什么用基于String的Float做到的吗

否则,我将不得不使用CodingKey引入String并使用计算get:

    enum CodingKeys: String, CodingKey {
       case name, age 
       case sTaxRate = "tax_rate"
    }
    var sTaxRate: String
    var taxRate: Float { return Float(sTaxRate) ?? 0.0 }

这种麻烦让我做的维护工作似乎超出了需要。

这是最简单的方法还是其他类型转换与DateDecodingStrategy类似的东西?

更新 :我应该注意:我也走了重写的路线

init(from decoder:Decoder)

但这是相反的方向,因为它迫使我自己做这一切。


问题答案:

不幸的是,我认为当前的JSONDecoderAPI中不存在这样的选项。只有一个选项可以将 特殊的
浮点值
与字符串表示形式相互转换。

手动解码的另一种可能的解决方案是为可以对其表示编码和从其表示解码的Codable任何内容定义包装器类型:LosslessStringConvertible``String

struct StringCodableMap<Decoded : LosslessStringConvertible> : Codable {

    var decoded: Decoded

    init(_ decoded: Decoded) {
        self.decoded = decoded
    }

    init(from decoder: Decoder) throws {

        let container = try decoder.singleValueContainer()
        let decodedString = try container.decode(String.self)

        guard let decoded = Decoded(decodedString) else {
            throw DecodingError.dataCorruptedError(
                in: container, debugDescription: """
                The string \(decodedString) is not representable as a \(Decoded.self)
                """
            )
        }

        self.decoded = decoded
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(decoded.description)
    }
}

然后,您可以拥有这种类型的属性并使用自动生成的Codable一致性:

struct Example : Codable {

    var name: String
    var age: Int
    var taxRate: StringCodableMap<Float>

    private enum CodingKeys: String, CodingKey {
        case name, age
        case taxRate = "tax_rate"
    }
}

虽然很不幸,但是现在您必须就taxRate.decoded如何与Float价值互动进行讨论。

但是,您总是可以定义一个简单的转发计算属性以减轻这种情况:

struct Example : Codable {

    var name: String
    var age: Int

    private var _taxRate: StringCodableMap<Float>

    var taxRate: Float {
        get { return _taxRate.decoded }
        set { _taxRate.decoded = newValue }
    }

    private enum CodingKeys: String, CodingKey {
        case name, age
        case _taxRate = "tax_rate"
    }
}

尽管这还没有达到应有的效果,但希望更高版本的JSONDecoderAPI会包含更多自定义解码选项,或者能够在CodableAPI本身内表达类型转换。

但是,创建包装器类型的一个优点是,也可以使用它来简化手动解码和编码。例如,使用手动解码:

struct Example : Decodable {

    var name: String
    var age: Int
    var taxRate: Float

    private enum CodingKeys: String, CodingKey {
        case name, age
        case taxRate = "tax_rate"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.name = try container.decode(String.self, forKey: .name)
        self.age = try container.decode(Int.self, forKey: .age)
        self.taxRate = try container.decode(StringCodableMap<Float>.self,
                                            forKey: .taxRate).decoded
    }
}


 类似资料:
  • 我的问题是:在PHP中,解析SRU请求返回的XML的最简单方法是什么? 例如,在浏览器中查看以下URL: http://explor.bcu.ac.uk/IntraLibrary-SRU?operation=searchRetrieve 此对公共存储库的查询返回符合SRU标准的格式良好的XML文档(它进行验证),在本例中返回两条记录。我使用过各种排列的simplexml\u load\u stri

  • 本文向大家介绍Python解析最简单的验证码,包括了Python解析最简单的验证码的使用技巧和注意事项,需要的朋友参考一下 最近在学python,正好遇到学校需要选宿舍,就用python写了一个抢宿舍的软件。其中有一个模块是用来登陆的,登陆的时候需要输入验证码,不过后来发现了直接可以绕过验证码直接登陆的bug。不过这是另外的话题,开始的时候我并没有发现这个隐藏起来的秘密,所以我就写了这个pytho

  • 问题内容: 我正在尝试使用JSON(使用simplejson)序列化python对象列表,并收到以下错误:对象“不可JSON序列化”。 该类是一个简单的类,其字段只有整数,字符串和浮点数,并且从一个父超类继承相似的字段,例如: foo,bar是我上面提到的简单类型。唯一棘手的事情是,ChildClass有时具有一个字段,该字段引用另一个对象(类型不是ParentClass或ChildClass)。

  • 本文向大家介绍重置mysql的root密码最简单的方法,包括了重置mysql的root密码最简单的方法的使用技巧和注意事项,需要的朋友参考一下 我的mysql版本 MYSQL V5.7.9,旧版本请使用: Mac OS X - 重置 MySQL Root密码 密码太多记不住??你是否忘记了Mac OS 的MySQL的root密码? 通过以下4步就可重新设置新密码: 1. 停止 mysql serv

  • 问题内容: 我需要通过Qt解析JSON对象。最简单/最快的方法是什么? 问题答案: 试试QJson。 QJson是积极开发的(如果没有记错的话,将由KDE使用)。最好的办法是直接签出源代码并自己构建。没有对QJson的依赖(Qt和CMake除外)。使用起来也很简单,请看一些用法示例: http://qjson.sourceforge.net/usage/

  • 本文向大家介绍简单了解JAVA变量类型及代码实例,包括了简单了解JAVA变量类型及代码实例的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了简单了解JAVA变量类型及代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在Java语言中,有类变量、实例变量、局部变量,所有的变量在使用前必须声明。声明普通变量如下: 类变量 类变量也称为