标签: codable

使用JSONEncoder将nil值编码为null

我正在使用Swift 4 JSONEncoder.我有一个Codable带有可选属性的结构,我希望这个属性在null值为时在生成的JSON数据中显示为值nil.但是,JSONEncoder丢弃该属性并且不将其添加到JSON输出.有没有办法配置,JSONEncoder以便它保留密钥并null在这种情况下将其设置为?

下面的代码片段会产生{"number":1},但我更愿意给它{"string":null,"number":1}:

struct Foo: Codable {
  var string: String? = nil
  var number: Int = 1
}

let encoder = JSONEncoder()
let data = try! encoder.encode(Foo())
print(String(data: data, encoding: .utf8)!)
Run Code Online (Sandbox Code Playgroud)

json ios swift4 codable

39
推荐指数
2
解决办法
5840
查看次数

Xcode 9.3中的Codable'没有初始化器'(Swift 4.1)

更新到Xcode 9.3(使用Swift 4.1)后,发现以下问题:

  1. 创建一个空项目,向其添加一个新的.swift文件并创建两个新类:

    创建为Codable类

    class CodableOne: Codable {
    
        let some: String
    
    }
    
    class CodableTwo: Codable {
    
        var some: String
    
    }
    
    Run Code Online (Sandbox Code Playgroud)

    建立成功

  2. 添加CodableOne类型的新常量CodableTwo:

    为CodableOne添加了一个新常量

    class CodableOne: Codable {
    
        let some: String
        let another: CodableTwo
    
    }
    
    class CodableTwo: Codable {
    
        var some: String
    
    }
    
    Run Code Online (Sandbox Code Playgroud)

    建立成功

  3. 现在将类移动CodableTwo到另一个文件(例如ViewController.swift)

    CodableTwo移动到另一个文件

    构建失败.

现在有一个错误,它不会消失.Codable类不应该需要初始化器(如前面的步骤所示).

关于这背后可能出现的问题及如何解决的任何想法将不胜感激!


PS Code在Xcode 9.2中不存在.也不清理项目/构建路径,重新安装Xcode 9.3也有帮助.

xcode swift codable swift4.1 xcode9.3

37
推荐指数
2
解决办法
3546
查看次数

使用JSONEncoder以Codable作为类型对变量进行编码

我设法让JSON和plist编码和解码都工作,但只能通过直接调用特定对象上的编码/解码函数.

例如:

struct Test: Codable {
    var someString: String?
}

let testItem = Test()
testItem.someString = "abc"

let result = try JSONEncoder().encode(testItem)
Run Code Online (Sandbox Code Playgroud)

这很好,没有问题.

但是,我试图获得一个只接受Codable协议一致性类型的函数并保存该对象.

func saveObject(_ object: Encodable, at location: String) {
    // Some code

    let data = try JSONEncoder().encode(object)

    // Some more code
}
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误:

无法使用类型'(Encodable)'的参数列表调用'encode'

看看编码函数的定义,似乎它应该能够接受Encodable,除非Value是一些我不知道的奇怪类型.

open func encode<Value>(_ value: Value) throws -> Data where Value : Encodable
Run Code Online (Sandbox Code Playgroud)

serialization protocols ios swift codable

35
推荐指数
1
解决办法
9158
查看次数

Swift:自定义编码器/解码器到字符串资源格式

我一直在玩,Codable并从文件中读取和写入JSON.现在我想写一个Coder可以读写iOS .strings文件的自定义.谁能帮我这个?我发现协议EncoderDecoder,但我不知道我应该实现此:

class StringsEncoder {}

extension StringsEncoder: Encoder {
    var codingPath: [CodingKey?] {
        return []
    }

    var userInfo: [CodingUserInfoKey : Any] {
        return [:]
    }

    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {

    }

    func unkeyedContainer() -> UnkeyedEncodingContainer {

    }

    func singleValueContainer() -> SingleValueEncodingContainer {

    }
}

extension StringsEncoder: Decoder {
    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {

    }

    func unkeyedContainer() throws -> …
Run Code Online (Sandbox Code Playgroud)

swift swift4 codable decodable encodable

35
推荐指数
1
解决办法
3928
查看次数

使用JSONEncoder对符合协议的类型进行编码/解码

我正在尝试使用Swift 4中的新JSONDecoder/Encoder找到符合swift协议的编码/解码结构数组的最佳方法.

我举了一个例子来说明问题:

首先,我们有一个协议Tag和一些符合这个协议的类型.

protocol Tag: Codable {
    var type: String { get }
    var value: String { get }
}

struct AuthorTag: Tag {
    let type = "author"
    let value: String
}

struct GenreTag: Tag {
    let type = "genre"
    let value: String
}
Run Code Online (Sandbox Code Playgroud)

然后我们有一个Type文章,它有一个标签数组.

struct Article: Codable {
    let tags: [Tag]
    let title: String
}
Run Code Online (Sandbox Code Playgroud)

最后,我们对文章进行编码或解码

let article = Article(tags: [AuthorTag(value: "Author Tag Value"), GenreTag(value:"Genre Tag Value")], title: "Article Title")


let jsonEncoder = JSONEncoder()
let jsonData = try …
Run Code Online (Sandbox Code Playgroud)

encoding json swift swift4 codable

32
推荐指数
3
解决办法
2万
查看次数

Swift 4 Codable; 如何使用单根级别密钥解码对象

我正在使用Codable带有JSON数据的Swift 4 协议.我的数据被格式化为在根级别有一个键,其中一个对象值包含我需要的属性,例如:

{
  "user": {
    "id": 1,
    "username": "jdoe"
  }
}
Run Code Online (Sandbox Code Playgroud)

我有一个User可以解码user密钥的结构:

struct User: Codable {
  let id: Int
  let username: String
}
Run Code Online (Sandbox Code Playgroud)

由于idusername是的性质user,而不是在根级别,我需要使一个包装类型,如下所示:

struct UserWrapper: Codable {
  let user: User
}
Run Code Online (Sandbox Code Playgroud)

然后,我可以通过UserWrapper,解码JSON ,并User解码.它似乎是很多冗余代码,因为我需要在我拥有的每种类型上都有一个额外的包装器.有没有办法避免这种包装模式或更正确/优雅的方式来处理这种情况?

json deserialization swift swift4 codable

32
推荐指数
4
解决办法
1万
查看次数

在Swift 4中实现自定义解码器

我想使用DecodableSwift 4中引入的新协议解码XML文档,但是,似乎没有符合Decoder协议的XML解码器的现有实现.

我的计划是使用SWXMLHash库来解析XML,然后可能使该XMLIndexer库中的类扩展Decoder协议,以便可以使用XMLIndexer(XMLIndexer返回SWXMLHash.parse(xmlString))实例初始化我的模型.

XMLIndexer + Decoder.swift

我的问题是我不知道如何实现Decoder协议,我似乎无法在网上找到任何解释它是如何完成的资源.我发现的每一个资源都严格地提到了JSONDecoderSwift标准库中包含的类,没有找到的资源解决了创建自己的自定义解码器的问题.

xml decoder swift swxmlhash codable

30
推荐指数
1
解决办法
7993
查看次数

如何使用Swift4中的Codable转换带有可选小数秒的日期字符串

我正在用Swift的Codable替换旧的JSON解析代码,并且遇到了一些麻烦.我想这不是一个可编码的问题,因为它是一个DateFormatter问题.

从结构开始

 struct JustADate: Codable {
    var date: Date
 }
Run Code Online (Sandbox Code Playgroud)

和一个json字符串

let json = """
  { "date": "2017-06-19T18:43:19Z" }
"""
Run Code Online (Sandbox Code Playgroud)

现在让我们解码

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

let data = json.data(using: .utf8)!
let justADate = try! decoder.decode(JustADate.self, from: data) //all good
Run Code Online (Sandbox Code Playgroud)

但是,如果我们更改日期以使其具有小数秒,例如:

let json = """
  { "date": "2017-06-19T18:43:19.532Z" }
"""
Run Code Online (Sandbox Code Playgroud)

现在它打破了.日期有时会以小秒数回归,有时则不会.我以前解决它的方式是在我的映射代码中我有一个转换函数,它尝试使用和不使用小数秒的dateFormats.我不太确定如何使用Codable来处理它.有什么建议?

nsdateformatter swift dateformatter swift4 codable

30
推荐指数
2
解决办法
6430
查看次数

使用带有密钥的可编码,有时是Int,有时是String

我有一个API,有时会id在JSON中作为Int 返回一个特定的键(在本例中),有时它将返回与String相同的键.如何使用codable来解析JSON?

struct GeneralProduct: Codable {
    var price:Double!
    var id:String?
    var name:String!

    private enum CodingKeys: String, CodingKey {
        case price = "p"
        case id = "i"
        case name = "n"
    }

    init(price:Double? = nil, id: String? = nil, name: String? = nil) {
        self.price = price
        self.id = id
        self.name = name
    }
}
Run Code Online (Sandbox Code Playgroud)

我不断收到此错误消息:Expected to decode String but found a number instead.返回数字的原因是因为id字段为空,并且当id字段为空时,它默认返回0作为可编码标识为数字的ID.我基本上可以忽略ID键但是可编码不会让我根据我的知识忽略它.处理这个问题的最佳方法是什么?

这是JSON.它非常简单

工作

{
  "p":2.12,
  "i":"3k3mkfnk3",
  "n":"Blue Shirt"
}
Run Code Online (Sandbox Code Playgroud)

错误 - 因为系统中没有id,它返回0作为默认值,可编码显然看作是与字符串相对的数字.

{
  "p":2.19, …
Run Code Online (Sandbox Code Playgroud)

json swift swift4 codable

26
推荐指数
4
解决办法
9040
查看次数

Swift 4 Decodable - 以enum为关键字典

我的数据结构有一个枚举作为键,我希望下面自动解码.这是一个错误还是一些配置问题?

import Foundation

enum AnEnum: String, Codable {
  case enumValue
}

struct AStruct: Codable {
  let dictionary: [AnEnum: String]
}

let jsonDict = ["dictionary": ["enumValue": "someString"]]
let data = try! JSONSerialization.data(withJSONObject: jsonDict,     options: .prettyPrinted)
let decoder = JSONDecoder()
do {
  try decoder.decode(AStruct.self, from: data)
} catch {
  print(error)
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误就是这个,似乎把dict与数组混淆了.

typeMismatch(Swift.Array,Swift.DecodingError.Context(codingPath:[Optional(__ lldb_expr_85.AStruct.(CodingKeys in _0E2FD0A9B523101D0DCD67578F72D1DD).dictionary)],debugDescription:"预计会解码数组,但会找到一个字典."))

swift codable

25
推荐指数
3
解决办法
1万
查看次数