(这是此问题的后续跟进:使用具有多个键的可解码协议.)
我有以下Swift代码:
let additionalInfo = try values.nestedContainer(keyedBy: UserInfoKeys.self, forKey: .age)
age = try additionalInfo.decodeIfPresent(Int.self, forKey: .realage)
Run Code Online (Sandbox Code Playgroud)
我知道如果我使用decodeIfPresent并且没有该属性,如果它是一个可选变量,它仍将正确处理它.
例如,以下JSON使用上面的代码解析它.
{
"firstname": "Test",
"lastname": "User",
"age": {"realage": 29}
}
Run Code Online (Sandbox Code Playgroud)
以下JSON也适用.
{
"firstname": "Test",
"lastname": "User",
"age": {"notrealage": 30}
}
Run Code Online (Sandbox Code Playgroud)
但以下不起作用.
{
"firstname": "Test",
"lastname": "User"
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能使所有3个例子都有效?是否有类似的东西decodeIfPresent了nestedContainer?
我有一些通过websocket连接进入的JSON消息.
// sample message
{
type: "person",
data: {
name: "john"
}
}
// some other message
{
type: "location",
data: {
x: 101,
y: 56
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用Swift 4和Codable协议将这些消息转换为正确的结构?
在Go中我可以做类似的事情:"嘿,此刻我只关心这个type领域而我对其余部分(data部分)不感兴趣." 它看起来像这样
type Message struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到Data的那样json.RawMessage,可以在以后解析.这是一个完整的示例https://golang.org/pkg/encoding/json/#example_RawMessage_unmarshal.
我可以在Swift中做类似的事情吗?喜欢(尚未尝试过)
struct Message: Codable {
var type: String
var data: [String: Any]
}
Run Code Online (Sandbox Code Playgroud)
然后switch在type将字典转换为适当的结构.那会有用吗?
我试图连接我的 API 数据以在单元格中查看它,但似乎我无法得到我的响应,而且总是== nil
下面的代码描述了 Country.SWIFT // Model.SWIFT // Response.SWIFT,它显示了如何我可以使用 Codable 获取 JSON 响应吗? CountryCell.SWIFT 展示了我如何使用它来调用 API API 图像的链接:

国家.SWIFT
struct Country: Decodable {
var CountryName = ""
var CountryImage = ""
var objectId = ""
// MARK: - Coding Keys
enum CodingKeys: String, CodingKey {
case CountryName = "CountryName"
case CountryImage = "CountryImage"
case objectId = "objectId"
}
//MARK: - Json Decoder
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// Parsing our attributes
self.CountryName …Run Code Online (Sandbox Code Playgroud) 我有以下Swift 4 Codable类,它继承自Realm的Object类型:
final class SearchResult: RealmSwift.Object, Codable {
@objc dynamic var name: String = ""
@objc dynamic var region: String = ""
enum CodingKeys: String, CodingKey {
case name = "name"
case region = "region"
}
}
Run Code Online (Sandbox Code Playgroud)
这里的期望是该init(from decoder: Decoder)方法被合成,所以我不必自己实现它,这是一个巨大的便利.但是,不实现这会产生以下编译器错误:
super.init isn't called on all paths before returning from initializer
有三种方法可以摆脱编译器错误,但没有一种方法是好的:
实现一个init(from decoder: Decoder)只调用的空方法super.init().这似乎阻止了合成,意味着没有任何实际解码,因为它只是一个空方法.
init(from decoder: Decoder)手动实现整个方法.这有效,但现在使用的乐趣Codable几乎消失了.
删除所有与Realm相关的代码.现在Codable按预期工作,但是,现在我不能再使用Realm了.
这对我来说似乎是一个Swift错误,因为它应该检测到init(from decoder: Decoder)实际上是在实现,而不是手动执行.
我不知道的任何建议或解决方法?
我创建了一个"可编码"结构来序列化数据集并将其编码为Json.除了计算属性没有显示在json字符串中之外,一切都工作得很好.如何在编码阶段包含计算属性.
例如:
struct SolidObject:Codable{
var height:Double = 0
var width:Double = 0
var length:Double = 0
var volume:Double {
get{
return height * width * length
}
}
}
var solidObject = SolidObject()
solidObject.height = 10.2
solidObject.width = 7.3
solidObject.length = 5.0
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(solidObject)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
} catch {
print(error)
}
Run Code Online (Sandbox Code Playgroud)
打印出"{"宽度":7.2999999999999998,"长度":5,"高度":10.199999999999999}"
我也很好奇有7.29999 ..而不是7.3但我的主要问题是"我怎么能包括"音量"这个json字符串呢?"?
我收到以下错误:
Generic parameter 'T' could not be inferred
在线: let data = try encoder.encode(obj)
这是代码
import Foundation
struct User: Codable {
var firstName: String
var lastName: String
}
let u1 = User(firstName: "Ann", lastName: "A")
let u2 = User(firstName: "Ben", lastName: "B")
let u3 = User(firstName: "Charlie", lastName: "C")
let u4 = User(firstName: "David", lastName: "D")
let a = [u1, u2, u3, u4]
var ret = [[String: Any]]()
for i in 0..<a.count {
let param = [
"a" : a[i], …Run Code Online (Sandbox Code Playgroud) 这是我的代码.但我不知道该如何设定价值.它必须手动完成,因为实际结构比这个例子稍微复杂一些.
有什么帮助吗?
struct Something: Decodable {
value: [Int]
enum CodingKeys: String, CodingKeys {
case value
}
init (from decoder :Decoder) {
let container = try decoder.container(keyedBy: CodingKeys.self)
value = ??? // < --- what do i put here?
}
}
Run Code Online (Sandbox Code Playgroud) 当符合Codable协议时,我不能轻易跳过非Codable类的可选属性
在Ride结构,我们要跳过的编码和解码的driver财产,只要把它nil解码时:
struct Ride: Codable {
public var number: String
public var passenger: Passenger? // Codable conforming
public var driver: Driver? // NSObject subclass, doesn't conform to Codable
enum CodingKeys: String, CodingKey {
case number
case passenger
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我得到一个编译错误
类型'驱动程序'不符合协议'可解码'
到目前为止,我提供的唯一解决方案是通过提供以下方法手动编码和解码:
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
number = try? values.decode(String.self, forKey: .number)
passenger = try? values.decode(Passenger.self, forKey: .passenger) …Run Code Online (Sandbox Code Playgroud) 我正在使用Swift 4和Xcode 9.2编写程序.我在编写可编码类(完全是类,而不是struct)时遇到了困难.当我尝试从另一个类继承一个类时,JSONEncoder不从子类(子)获取所有属性.请看这个:
class BasicData: Encodable {
let a: String
let b: String
init() {
a = "a"
b = "b"
}
}
class AdditionalData: BasicData {
let c: String
init(c: String) {
self.c = c
}
}
let encode = AdditionalData(c: "c")
do {
let data = try JSONEncoder().encode(encode)
let string = String(data: data, encoding: .utf8)
if let string = string {
print(string)
}
} catch {
}
Run Code Online (Sandbox Code Playgroud)
它会打印出来: {"a":"a","b":"b"}
但我需要这个: {"a":"a","b":"b","c":"c"}
它看起来像c类的属性AdditionalData只是失去了某处,不知何故.
所以问题是:如果我有使用协议编码的类Encodable如何正确地创建子类(此类的子类,继承)类?
我会感谢任何帮助或建议.
我尝试使用Swift 4.1的新功能在JSON解码期间将snake-case转换为camelCase.
这是一个例子:
struct StudentInfo: Decodable {
internal let studentID: String
internal let name: String
internal let testScore: String
private enum CodingKeys: String, CodingKey {
case studentID = "student_id"
case name
case testScore
}
}
let jsonString = """
{"student_id":"123","name":"Apple Bay Street","test_score":"94608"}
"""
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decoded = try decoder.decode(StudentInfo.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
Run Code Online (Sandbox Code Playgroud)
我需要提供自定义,CodingKeys因为convertFromSnakeCase策略无法推断首字母缩略词或首字母缩写词(例如studentID)的大写字母,但我希望convertFromSnakeCase策略仍然适用testScore.但是,解码器抛出错误("没有与键CodingKeys相关的值"),似乎我不能同时使用convertFromSnakeCase策略和自定义 …