Ios Swift 4和xB7;数据转换

Ios Swift 4和xB7;数据转换,ios,json,swift,Ios,Json,Swift,我正在iOS中创建一个模拟时钟显示器,它还显示太阳正午和时钟正午之间的差异,因此我需要知道太阳正午的时间,以便计算该差异 此api调用:http://api.usno.navy.mil/rstt/oneday?date=today&coords=51.1,-1.0&tz=1产生以下结果(一些不相关的字段被丢弃): { “年份”:2018年, “月”:6, “天”:18, “lon”:-1.000000, “lat”:51.100000, "tz":1,, “圣代”:[ {“phen”:“BC”,

我正在iOS中创建一个模拟时钟显示器,它还显示太阳正午和时钟正午之间的差异,因此我需要知道太阳正午的时间,以便计算该差异

此api调用:
http://api.usno.navy.mil/rstt/oneday?date=today&coords=51.1,-1.0&tz=1
产生以下结果(一些不相关的字段被丢弃):

{
“年份”:2018年,
“月”:6,
“天”:18,
“lon”:-1.000000,
“lat”:51.100000,
"tz":1,,
“圣代”:[
{“phen”:“BC”,“time”:“04:02”},
{“phen”:“R”,“time”:“04:49”},

{“phen”:“U”,“time”:“13:05”},这方面的东西应该是可行的。基本上,您希望为
phen
项创建一个类。您甚至可以对现象类型使用枚举来提高可读性

我相信您还可以做其他事情来提高可读性,比如定义自己的
CodingKeys
enum来为属性提供更好的名称,但这取决于您自己。这应该让您开始

struct SolarData: Decodable {

    struct Phenomenon: Decodable {

        enum Kind: String, Decodable {
            case
            beginCivilTwilight = "BC",
            rise = "R",
            upperTransit = "U",
            set = "S",
            endCivilTwilight = "EC",
            lowerTransit = "L"
        }

        var phen: Kind
        var time: String
    }

    let year: Int
    let month: Int
    let day: Int
    let lon: Double
    let lat: Double
    let tz: Double
    let sundata:  [Phenomenon]

    /// The number of minutes past clock noon at which solar noon occurs.
    public var solarNoonOffset: Int {
        let noon = sundata
            .first { $0.phen == .upperTransit }
            .map { $0.time }
        let solarNoonHour = Int(noon!.prefix(2))
        let solarNoonMins = Int(noon!.suffix(2))
        let offset        = (solarNoonHour! - 12) * 60 + solarNoonMins!
        return offset
    }
}

let testJson = """
{
    "year":2018,
    "month":6,
    "day":18,
    "lon":-1.000000,
    "lat":51.100000,
    "tz":1,
    "sundata":[
        {"phen":"BC", "time":"04:02"},
        {"phen":"R", "time":"04:49"},
        {"phen":"U", "time":"13:05"},
        {"phen":"S", "time":"21:22"},
        {"phen":"EC", "time":"22:09"}]
}
"""

let solarData = try JSONDecoder().decode(SolarData.self, from: testJson.data(using: .utf8)!)

print("Solar Noon Offset: \(solarData.solarNoonOffset)")

您必须将NSDateFormatter与“HH:mm”一起使用模板,据我所知,它声明另一个具有属性
phen
time
的结构。使该结构符合
Codable
,然后将
sundata
声明为该结构的数组。同意@Paulw11-如果您将
sundata
结构声明为
phen
(您可以将其定义为
enum Phen:String、Decodable
time
,然后您将能够使用类似
let noon=sundata.first(其中:{$0.Phen==.U})!.time
而不是您的多行声明。我同意@Paulw11更好地使用另一个结构,替代方法是
sundata.lazy.first{$0[“Phen]==“U”}?[“time”]
。另外,请使用日期格式化程序提取日期,并让其返回可选值,因为服务器总是会返回错误数据,这只是一个字符串。使用日期格式化程序处理“HH:MM”当然是显而易见的事情(一旦有人提到它)!谢谢。我觉得SunData本身应该是一个结构,但被数组抛出。但它是一个SunData属性数组,正在等待提取。在被指出后也很明显。再次感谢。谢谢。这个“现象”“struct正是我为简化数据提取而寻找的指针类型。
struct SolarData: Decodable {
    let year: Int
    let month: Int
    let day: Int
    let lon: Double
    let lat: Double
    let tz: Double
    let sundata:  Array<[String: String]>

    /// The number of minutes past clock noon at which solar noon occurs.
    public var solarNoonOffset: Int {
        let noon = sundata
                      .filter { $0["phen"] == "U" }
                      .flatMap { $0 }
                      .filter { $0.0 == "time" }[0]
                      .value
        let solarNoonHour = Int(noon.prefix(2))
        let solarNoonMins = Int(noon.suffix(2))
        let offset        = (solarNoonHour! - 12) * 60 + solarNoonMins!
        return offset
    }
}
struct SolarData: Decodable {

    struct Phenomenon: Decodable {

        enum Kind: String, Decodable {
            case
            beginCivilTwilight = "BC",
            rise = "R",
            upperTransit = "U",
            set = "S",
            endCivilTwilight = "EC",
            lowerTransit = "L"
        }

        var phen: Kind
        var time: String
    }

    let year: Int
    let month: Int
    let day: Int
    let lon: Double
    let lat: Double
    let tz: Double
    let sundata:  [Phenomenon]

    /// The number of minutes past clock noon at which solar noon occurs.
    public var solarNoonOffset: Int {
        let noon = sundata
            .first { $0.phen == .upperTransit }
            .map { $0.time }
        let solarNoonHour = Int(noon!.prefix(2))
        let solarNoonMins = Int(noon!.suffix(2))
        let offset        = (solarNoonHour! - 12) * 60 + solarNoonMins!
        return offset
    }
}

let testJson = """
{
    "year":2018,
    "month":6,
    "day":18,
    "lon":-1.000000,
    "lat":51.100000,
    "tz":1,
    "sundata":[
        {"phen":"BC", "time":"04:02"},
        {"phen":"R", "time":"04:49"},
        {"phen":"U", "time":"13:05"},
        {"phen":"S", "time":"21:22"},
        {"phen":"EC", "time":"22:09"}]
}
"""

let solarData = try JSONDecoder().decode(SolarData.self, from: testJson.data(using: .utf8)!)

print("Solar Noon Offset: \(solarData.solarNoonOffset)")