解码期间未从其他结构中找到 CodingKey

如何解决解码期间未从其他结构中找到 CodingKey

我正在尝试使用 dateString 结构中的解析日期字符串 (Datum) 在 AzimuthAtDate 类中构建新的日期对象...

{
    "11": [{
        "name": "Sun","date": "2021-01-26","rising": [{
            "coord": "113.6681","hour": "07:16"
        }],"transit-sup": [{
            "coord": "32.4711","hour": "12:16"
        }],"setting": [{
            "coord": "246.4743","hour": "17:17"
        }]
    }]
}
struct Datum: Codable,CustomStringConvertible {

    let name: String
    let dateString: String
    let isoDate: Date?
    let rising: [AzimuthAtDate]
    let transit: [ElevationAtDate]
    let setting: [AzimuthAtDate]
    
    enum CodingKeys: String,CodingKey {
        case name
        case dateString = "date"
        case isoDate
        case rising = "rising"
        case transit = "transit-sup"
        case setting = "setting"
    }

    init(from decoder: Decoder) throws {
        let con = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try con.decode(String.self,forKey: .name)
        self.dateString = try con.decode(String.self,forKey: .dateString)
        self.isoDate = try con.decode(Date.self,forKey: .dateString)
        self.rising = decodeAzimuthAtDate(decoder: decoder,key: .rising)
        self.transit = decodeElevationAtDate(decoder: decoder,key: .transit)
        self.setting = decodeAzimuthAtDate(decoder: decoder,key: .setting)
    }
}

class CoordHour: Codable {
    let coord: String
    let hour: String
    var isoDate: Date?
    init(coord: String,hour: String,isoDate: Date?) {
        self.coord = coord
        self.hour = hour
        self.isoDate = isoDate
    }
}

但是在尝试从 Datum.CodingKeys 中访问 AzimuthAtDate 的密钥时,datumContainer 没有密钥。所以我收到这样的错误: keyNotFound(CodingKeys(stringValue: "date",intValue: nil) ... debugDescription: "No value associated with key CodingKeys(stringValue: \"date\",intValue: nil) (\"date\").",underlyingError: nil))

class AzimuthAtDate: CoordHour {
    required init(from decoder: Decoder) throws {
        let coordHourContainer = try decoder.container(keyedBy: CoordHour.CodingKeys.self)
        let coord = try coordHourContainer.decode(String.self,forKey: .coord)
        let hour = try coordHourContainer.decode(String.self,forKey: .hour)
        
        print("coord:\(coord) - hour:\(hour)") // prints correct info
        
        let datumContainer = try decoder.container(keyedBy: Datum.CodingKeys.self)

        print("datumContainer keys:\(datumContainer.allKeys)") // shows []
        
        let dateString = try datumContainer.decode(String.self,forKey: .dateString)
        print("dateString:\(dateString)")
        
        let currentTZ = TimeZone.currentOffsetFromUTCString
        let isoDateString = "\(dateString)T\(hour)\(currentTZ)"
        let isoDate = DateFormatter.Iso.date(from: isoDateString)
        
        super.init(coord: coord,hour: hour,isoDate: isoDate)
    }
}

AzimuthAtDate 类中,我如何才能访问 Datum.dateString 键以便我可以使用它的值来形成 isoDate

func decodeAzimuthAtDate(decoder: Decoder,key: Datum.CodingKeys) -> [AzimuthAtDate] {
    var result = [AzimuthAtDate]()
    do {
        let con = try decoder.container(keyedBy: Datum.CodingKeys.self)
        if let az = try con.decode([AzimuthAtDate]?.self,forKey: key)?.first {
            result.append(az)
        }
    } catch let error {
        print(error)
    }
    return result
}

解决方法

忽略解码和 JSON 并用更一般的术语思考问题。内部结构如何知道将其作为属性保存的外部结构?

例如,这里会发生什么:

struct InnerStruct {
    func test() {
        // ?
    }
}
struct OuterStruct {
    let inner = InnerStruct()
    let other = "howdy"
}

... 为了调用 innertest() 打印 "howdy"?显然,inner 的 InnerStruct 需要一个 引用 到持有它的 OuterStruct。像这样:

struct InnerStruct {
    weak var container : OuterStruct?
    func test() {
        print(self.container?.other)
    }
}
class OuterStruct {
    var inner = InnerStruct()
    let other = "howdy"
    init() {
        self.inner.container = self
    }
}
let outerStruct = OuterStruct()
outerStruct.inner.test()

这就是你需要做的事情。您的内部类型需要一个属性,该属性是对其容器的引用,以便它们可以“看到”该日期,并且您需要在配置其他所有内容时设置该引用。否则,您甚至可以仅使用外部日期来设置内部类型的属性。但是你不能把它作为解码的一部分;必须在一切配置完成后才能完成。

以下是一种基于您的数据的简单示例(这是 Playground 代码):

let json = """
{
    "11": [{
        "name": "Sun","date": "2021-01-26","rising": [{
            "coord": "113.6681","hour": "07:16"
        }],"transit-sup": [{
            "coord": "32.4711","hour": "12:16"
        }],"setting": [{
            "coord": "246.4743","hour": "17:17"
        }]
    }]
}
"""

let jsonData = json.data(using: .utf8)

class Inner: Decodable,CustomStringConvertible {
    let coord : String
    let hour : String
    var outerDate : String?
    var description : String {
        return (self.coord + ";" + self.hour + ";" + (self.outerDate ?? ""))
    }
}
struct Outer: Decodable {
    let name: String
    let date: String
    let rising: [Inner]
    let transitsup: [Inner]
    let setting: [Inner]
    enum CodingKeys: String,CodingKey {
        case name
        case date
        case rising
        case transitsup = "transit-sup"
        case setting
    }
}
struct Main: Decodable {
    let x: [Outer]
    enum CodingKeys: String,CodingKey {
        case x = "11"
    }
}
let result = try! JSONDecoder().decode(Main.self,from: jsonData!)
let outers = result.x
for anOuter in outers {
    let date = anOuter.date
    for anInner in anOuter.rising {
        anInner.outerDate = date
    }
    for anInner in anOuter.setting {
        anInner.outerDate = date
    }
    for anInner in anOuter.transitsup {
        anInner.outerDate = date
    }
}
print(outers)

如您所见,当我们完成后,每个 Inner 都知道其容器的 date。因此它可以继续计算日期时间。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-