如何解码包含日期信息的 JSON?

Posted

技术标签:

【中文标题】如何解码包含日期信息的 JSON?【英文标题】:How to decode JSON that contains a date information? 【发布时间】:2020-01-08 10:45:12 【问题描述】:

我的 JSON 结构为:

"symbol": "SNAP",

"stock_exchange_short": "NYSE",
"timezone_name": "America/New_York",
"intraday": 

    "2019-12-20 15:59:00": 
        "open": "15.55",
        "close": "15.55",
        "high": "15.55",
        "low": "15.52",
        "volume": "670218"
    ,
    "2019-12-20 15:58:00": 
        "open": "15.55",
        "close": "15.55",
        "high": "15.55",
        "low": "15.54",
        "volume": "284225"
    ,
   ...

关于如何实现日期信息的任何想法 我试图像这样解析它:

public struct WorldTradingIntradayData: Decodable 
    let symbol : String
    let stock_exchange_short : String
    let timezone_name : String
    let intraday : Intraday?
 
public struct Intraday: Decodable 
    let dateTime: WorldTradingIntradayDetails

 public struct WorldTradingIntradayDetails: Decodable 
     let open : String
     let close : String
     let high : String
     let low : String
     let volume : String
    

但它并没有按预期工作。 知道如何做到这一点吗?

【问题讨论】:

在你的解码部分实现do/catch来帮助你找出错误 intraday 应该是数组而不是对象! 这能回答你的问题吗? How to parse one block of JSON data instead of the entire JSON sequence 【参考方案1】:

我认为它应该被视为字符串,然后如果要将其转换为日期,则需要将空间更改为T以创建dateFormatter

struct WorldTradingIntradayData: Decodable 
    let symbol: String
    let stockExchangeShort: String
    let timezoneName: String
    let intraday: [String: Intraday]

    enum CodingKeys: String, CodingKey 
        case symbol
        case stockExchangeShort = "stock_exchange_short"
        case timezoneName = "timezone_name"
        case intraday
    


struct Intraday: Decodable 
    let intradayOpen: String
    let close: String
    let high: String 
    let low: String
    let volume: String

    enum CodingKeys: String, CodingKey 
        case intradayOpen = "open"
        case close
        case high
        case low 
        case volume
    

【讨论】:

【参考方案2】:

替换

let intraday : Intraday?

let intraday : [String:WorldTradingIntradayDetails]

并彻底摆脱public struct Intraday: Decodable

【讨论】:

【参考方案3】:

现在回答太晚了,如果有人仍然需要它,就添加完整的代码。

  struct WorldTradingIntradayData: Codable 
    let symbol: String
    let stock_exchange_short: String
    let timezone_name: String
    let intraday: [String: DataModel]
  

  struct DataModel: Codable 
    let open: String
    let close: String
    let high: String
    let low: String
    let volume: String
  

  let resultsJson = """

  "symbol": "SNAP",

  "stock_exchange_short": "NYSE",
  "timezone_name": "America/New_York",
  "intraday": 

    "2019-12-20 15:59:00": 
        "open": "15.55",
        "close": "15.55",
        "high": "15.55",
        "low": "15.52",
        "volume": "670218"
    ,
    "2019-12-20 15:58:00": 
        "open": "15.55",
        "close": "15.55",
        "high": "15.55",
        "low": "15.54",
        "volume": "284225"
    
  

""".data(using: .utf8)!

  do 
    let reponseData = try JSONDecoder().decode(WorldTradingIntradayData.self, from: resultsJson)

    //get all dates
    let dateArray = reponseData.intraday.keys.map$0
    print(dateArray)

    // use the data from `intraday` array like this to get the data
    for date in dateArray 
        let data = reponseData.intraday[date]
        print(data?.open)
    

  

【讨论】:

【参考方案4】:

要求 json creator 以以下格式发送数据,您需要有一个常量键来解析。 2019-12-20 15:59:00时间不应该用作键


    "intraday": [
            "dateTime": "2019-12-20 15:59:00",
            "data": 
                "open": "15.55",
                "close": "15.55",
                "high": "15.55",
                "low": "15.52",
                "volume": "670218"
            ,
            "dateTime": "2019-12-20 15:59:00",
            "data": 
                "open": "15.55",
                "close": "15.55",
                "high": "15.55",
                "low": "15.52",
                "volume": "670218"
            
    ]

【讨论】:

请求 API 的所有者更改格式通常不是一种前进的方式,特别是对于类似来自第三方的 API 的情况。 发答​​案的是你,不是我 别介意,我只是在询问实际问题的答案:) 我也在寻找答案,如何解析这种情况。 如果您也在寻找上述问题的答案,那么为什么要发布这样的答案? 我试图要求公司按照您的建议更改格式,他们告诉我“您可以通过在您的请求中添加 &formatted=false 来做到这一点。”【参考方案5】:

我在 URL 请求中添加了 &formatted=false,得到了一个不同的格式,它可以正常工作并且易于处理。

【讨论】:

以上是关于如何解码包含日期信息的 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用数组对 API 数据进行 Json 解码?

如何解码包含数组 Swift 4 的 JSON 文件?

bson.json_util 日期时间编码和解码最佳实践

JSON 意外语法错误 - 日期解析/编码/解码

iOS:光泽日期解码问题

2018-04-09(JSON.parse和JSON.stringify的编码解码)