我正在努力更好地理解解码器初始化器和JSON解码.此代码运行并生成预期结果:

let json = """
[
    {
        "firstName": "Jon",
        "lastName": "Dough"
   },
    {
        "firstName": "Jane",
        "lastName": "Dough"
    }
]
""".data(using: .utf8)!

struct Character: Codable {
    var firstName: String
    var lastName: String
    
     enum CodingKeys: String, CodingKey {
        case
            firstName,
            lastName
    }
 
    init(from decoder: Decoder) throws {
        
        let data = try decoder.container(keyedBy: CodingKeys.self)

        firstName = try data.decode(String.self, forKey: .firstName)
        lastName = try data.decode(String.self, forKey: .lastName)
    }
}

let decoder = JSONDecoder()
func doDecode() -> [Character] {
    do {
        var cast = try decoder.decode([Character].self, from: json)
        return cast
    } catch {
        print("Error")
    }
    return []
}

let cast = doDecode()

print("# Cs \(cast.count)")

当我try 添加助手函数时,

extension Character {
    private func tryDecode<T: Codable>(_ data: KeyedDecodingContainer<CodingKeys>, type: T.Type, forKey: CodingKeys, empty: T) -> T {
        do {
            let result = try data.decode(T.self, forKey: forKey)
            return result
        } catch { return empty }
    }
}

我收到一个编译器错误:

在初始化之前使用的变量‘self.firstName’

当我从初始值设定项调用它时:

init(from decoder: Decoder) throws {
    let data = try decoder.container(keyedBy: CodingKeys.self)
    firstName = tryDecode(data, type: String.self, forKey: Character.CodingKeys.firstName, empty: "")
    lastName = tryDecode(data, type: String.self, forKey: Character.CodingKeys.lastName, empty: "")
}

我输入了带有和不带有完整路径的"Forkey:".结果是一样的.

我做错了什么?为什么编译器不知道"Forkey:"参数引用的是枚举,而不是self.firstName?

我正在Xcode操场上运行最新发布的Xcode&amp;MacOS操作系统.

推荐答案

与你的问题无关,但性格是天生的Swift 类型.您应该为您的自定义 struct Select 另一个名称,以避免在引用本机类型时添加SWIFT前缀.

关于实际问题,您已经将您的方法声明为实例方法,因此在try 调用它之前,它需要初始化所有属性.考虑到您的方法不需要访问Self,您可以将您的方法声明为静态方法,以避免必须初始化 struct 的所有属性.在调用您的方法时,您需要添加 struct 前缀/.

Char.tryDecode(...

struct Char: Codable {
    var firstName: String
    var lastName: String
    
     enum CodingKeys: String, CodingKey {
        case
            firstName,
            lastName
    }
 
    init(from decoder: Decoder) throws {
        let data = try decoder.container(keyedBy: CodingKeys.self)
        firstName = Char.tryDecode(data, type: String.self, forKey: Char.CodingKeys.firstName, empty: "")
        lastName = Char.tryDecode(data, type: String.self, forKey: Char.CodingKeys.lastName, empty: "")
    }
}

extension Char {
    private static func tryDecode<T: Codable>(_ data: KeyedDecodingContainer<CodingKeys>, type: T.Type, forKey: CodingKeys, empty: T) -> T {
        do {
            return try data.decode(T.self, forKey: forKey)
        } catch {
            return empty
        }
    }
}

let json = Data("""
[
    {
        "firstName": "Jon",
        "lastName": "Dough"
   },
    {
        "firstName": "Jane",
        "lastName": "Dough"
    }
]
""".utf8)

let decoder = JSONDecoder()
func doDecode() -> [Char] {
    do {
        return try decoder.decode([Char].self, from: json)
    } catch {
        print("Error")
    }
    return []
}

let cast = doDecode()

print("# Cs \(cast.count)")

Swift相关问答推荐

解析SON数据的API调用有什么问题?

使用SWIFT宏从另一个枚举添加 case

SWIFT中MAP的静态方法包装器

如何获取SCNCamera正在查看的网格点(SCNNode)的局部坐标和局部法线?

SwiftUI正在初始化不带状态变量的绑定变量

RxSwift .debounce,.throttle用于分页

如何使用AsyncTimerSequence获取初始时钟,然后在指定的时间间隔内开始迭代?

从SwiftUI使用UIPageView时,同一页面连续显示两次的问题

如何绑定环境变量ios17

循环字典中的数组

SwiftUI路径平滑连接两条线

swiftui中服务端图片如何设计view并赋予rotationEffect?

Swift 有没有办法在不使用 switch 语句的情况下获取关联值?

将阻塞函数集成到 Swift 异步中

仅在 Swift 中创建 Setter

AES 加密和解密

Type 应该采用什么协议来让泛型函数将任何数字类型作为 Swift 中的参数?

自动布局:获取 UIImageView 高度以正确计算单元格高度

如何判断 firebase 数据库值是否存在?

枚举大小写的原始值必须是文字