我正在开发一个应用程序而不是从fitbitapi中提取数据并在tableview中显示它,但是当我尝试将从Web API获取的数据附加到原始模型时,这是我的代码
for json in jsons.values {
print("json is \(json)")
if let Json = json as? [String : Any]{
var healthData : StepStats? = nil
if let date = Json["dateTime"] as? String,
let value = Json["value"] as? Int{
healthData = StepStats(dateTime : date, value : value as AnyObject)
}
if let HealthData = healthData {
model.append(HealthData)
}
}
else {
print("Unexpected Error")
}
每次运行此代码时,都会产生意外错误,而Json = nil,初始json就在这里
{
dateTime = "2018-04-15";
value = 0;
},
{
dateTime = "2018-04-16";
value = 6969;
},
}
我认为这是我收到的Json数据格式没有很好的格式化,或者我的代码有什么问题吗?请帮助我,我是新手,因为它可能是基本的错误,但任何帮助都会受到赞赏。
未解析的数据就像这样
Optional("{\"activities-steps\":[{\"dateTime\":\"2018-04-17\",\"value\":\"7170\"},{\"dateTime\":\"2018-04-18\",\"value\":\"6443\"},{\"dateTime\":\"2018-04-19\",\"value\":\"11254\"},{\"dateTime\":\"2018-04-20\",\"value\":\"5771\"},{\"dateTime\":\"2018-04-21\",\"value\":\"33\"},{\"dateTime\":\"2018-04-22\",\"value\":\"2697\"},{\"dateTime\":\"2018-04-23\",\"value\":\"11\"},{\"dateTime\":\"2018-04-24\",\"value\":\"8\"},{\"dateTime\":\"2018-04-25\",\"value\":\"0\"},{\"dateTime\":\"2018-04-26\",\"value\":\"0\"},{\"dateTime\":\"2018-04-27\",\"value\":\"0\"},{\"dateTime\":\"2018-04-28\",\"value\":\"389\"},{\"dateTime\":\"2018-04-29\",\"value\":\"4916\"},{\"dateTime\":\"2018-04-30\",\"value\":\"0\"},{\"dateTime\":\"2018-05-01\",\"value\":\"0\"},{\"dateTime\":\"2018-05-02\",\"value\":\"0\"},{\"dateTime\":\"2018-05-03\",\"value\":\"0\"},{\"dateTime\":\"2018-05-04\",\"value\":\"1929\"},{\"dateTime\":\"2018-05-05\",\"value\":\"0\"},{\"dateTime\":\"2018-05-06\",\"value\":\"0\"},{\"dateTime\":\"2018-05-07\",\"value\":\"0\"},{\"dateTime\":\"2018-05-08\",\"value\":\"2818\"},{\"dateTime\":\"2018-05-09\",\"value\":\"6990\"},{\"dateTime\":\"2018-05-10\",\"value\":\"6558\"},{\"dateTime\":\"2018-05-11\",\"value\":\"15434\"},{\"dateTime\":\"2018-05-12\",\"value\":\"0\"},{\"dateTime\":\"2018-05-13\",\"value\":\"0\"},{\"dateTime\":\"2018-05-14\",\"value\":\"0\"},{\"dateTime\":\"2018-05-15\",\"value\":\"0\"},{\"dateTime\":\"2018-05-16\",\"value\":\"0\"},{\"dateTime\":\"2018-05-17\",\"value\":\"0\"}]}")
答案 0 :(得分:0)
您的打印输出看起来几乎像JSON,但事实并非如此。我猜你打印出一个从错误的JSONSerialization
派生出来的对象,它将自己决定从字符串中解析它是什么。通过应用Codable
协议,可以更加轻松地以更加通用的方式控制这一点。鉴于您可以运行以下Playground
import Cocoa
let jsonData = """
[
{
"dateTime":"2018-04-15",
"value":0
},
{
"dateTime":"2018-04-16",
"value":6969
}
]
""".data(using: .utf8)!
struct HealthData: Codable {
let date: Date
let value: Int
private enum CodingKeys: String, CodingKey {
case date = "dateTime"
case value
}
}
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
let datas = try decoder.decode([HealthData].self, from: jsonData)
print(datas)
} catch {
print(error)
}
极大地简化了您的解析策略,因为大多数解析策略由JSONDecoder
处理,您甚至可以指定日期格式化程序。如果我的猜测错误,请随时添加实际 JSON,但请发布您从服务中获得的String
内容,而不是一半解析结构。
答案 1 :(得分:0)
即使StackOverflow建议我编辑上一个答案,我也会添加另一个答案,但我不能不注意到添加你的" new"未解析的数据基本上将这个问题变成了一个完全不同的问题。通常你应该问另一个问题,也许你想在另一个问题上继续发表评论。足够的元,现在为答案。
当你的"未解析的数据"在技术上是正确的,它在两个方面仍然非常不方便。线性化的选项最终被转义,所以你的所有双引号都将被转义(并且有大量的正确JSON)并且不会出现在StackOverflow上难以阅读的新行,你应该尝试保留你的行并不比典型浏览器窗口的宽度大得多。转义双引号可以通过简单地展开可选(使用!
)来处理,但添加漂亮的换行有点困难。但是,由于您的JSON基本上是正确的,我现在可以使用它来展示Codable
协议的其他一些精确性。如果你运行这个游乐场:
import Cocoa
let string = "{\"activities-steps\":[{\"dateTime\":\"2018-04-17\",\"value\":\"7170\"},{\"dateTime\":\"2018-04-18\",\"value\":\"6443\"},{\"dateTime\":\"2018-04-19\",\"value\":\"11254\"},{\"dateTime\":\"2018-04-20\",\"value\":\"5771\"},{\"dateTime\":\"2018-04-21\",\"value\":\"33\"},{\"dateTime\":\"2018-04-22\",\"value\":\"2697\"},{\"dateTime\":\"2018-04-23\",\"value\":\"11\"},{\"dateTime\":\"2018-04-24\",\"value\":\"8\"},{\"dateTime\":\"2018-04-25\",\"value\":\"0\"},{\"dateTime\":\"2018-04-26\",\"value\":\"0\"},{\"dateTime\":\"2018-04-27\",\"value\":\"0\"},{\"dateTime\":\"2018-04-28\",\"value\":\"389\"},{\"dateTime\":\"2018-04-29\",\"value\":\"4916\"},{\"dateTime\":\"2018-04-30\",\"value\":\"0\"},{\"dateTime\":\"2018-05-01\",\"value\":\"0\"},{\"dateTime\":\"2018-05-02\",\"value\":\"0\"},{\"dateTime\":\"2018-05-03\",\"value\":\"0\"},{\"dateTime\":\"2018-05-04\",\"value\":\"1929\"},{\"dateTime\":\"2018-05-05\",\"value\":\"0\"},{\"dateTime\":\"2018-05-06\",\"value\":\"0\"},{\"dateTime\":\"2018-05-07\",\"value\":\"0\"},{\"dateTime\":\"2018-05-08\",\"value\":\"2818\"},{\"dateTime\":\"2018-05-09\",\"value\":\"6990\"},{\"dateTime\":\"2018-05-10\",\"value\":\"6558\"},{\"dateTime\":\"2018-05-11\",\"value\":\"15434\"},{\"dateTime\":\"2018-05-12\",\"value\":\"0\"},{\"dateTime\":\"2018-05-13\",\"value\":\"0\"},{\"dateTime\":\"2018-05-14\",\"value\":\"0\"},{\"dateTime\":\"2018-05-15\",\"value\":\"0\"},{\"dateTime\":\"2018-05-16\",\"value\":\"0\"},{\"dateTime\":\"2018-05-17\",\"value\":\"0\"}]}"
let jsonData = string.data(using: .utf8)!
struct Step: Codable {
let value: String
let dateTime : Date
}
struct Activity: Codable {
let steps: [Step]
enum CodingKeys: String, CodingKey {
case steps = "activities-steps"
}
}
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
let activity = try decoder.decode(Activity.self, from: jsonData)
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .formatted(formatter)
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(activity)
print(String(data: data, encoding: .utf8)!)
} catch {
print(error)
}
这将打印出以下漂亮的JSON:
{
"activities-steps" : [
{
"value" : "7170",
"dateTime" : "2018-04-17"
},
{
"value" : "6443",
"dateTime" : "2018-04-18"
},
{
"value" : "11254",
"dateTime" : "2018-04-19"
},
{
"value" : "5771",
"dateTime" : "2018-04-20"
},
{
"value" : "33",
"dateTime" : "2018-04-21"
},
{
"value" : "2697",
"dateTime" : "2018-04-22"
},
{
"value" : "11",
"dateTime" : "2018-04-23"
},
{
"value" : "8",
"dateTime" : "2018-04-24"
},
{
"value" : "0",
"dateTime" : "2018-04-25"
},
{
"value" : "0",
"dateTime" : "2018-04-26"
},
{
"value" : "0",
"dateTime" : "2018-04-27"
},
{
"value" : "389",
"dateTime" : "2018-04-28"
},
{
"value" : "4916",
"dateTime" : "2018-04-29"
},
{
"value" : "0",
"dateTime" : "2018-04-30"
},
{
"value" : "0",
"dateTime" : "2018-05-01"
},
{
"value" : "0",
"dateTime" : "2018-05-02"
},
{
"value" : "0",
"dateTime" : "2018-05-03"
},
{
"value" : "1929",
"dateTime" : "2018-05-04"
},
{
"value" : "0",
"dateTime" : "2018-05-05"
},
{
"value" : "0",
"dateTime" : "2018-05-06"
},
{
"value" : "0",
"dateTime" : "2018-05-07"
},
{
"value" : "2818",
"dateTime" : "2018-05-08"
},
{
"value" : "6990",
"dateTime" : "2018-05-09"
},
{
"value" : "6558",
"dateTime" : "2018-05-10"
},
{
"value" : "15434",
"dateTime" : "2018-05-11"
},
{
"value" : "0",
"dateTime" : "2018-05-12"
},
{
"value" : "0",
"dateTime" : "2018-05-13"
},
{
"value" : "0",
"dateTime" : "2018-05-14"
},
{
"value" : "0",
"dateTime" : "2018-05-15"
},
{
"value" : "0",
"dateTime" : "2018-05-16"
},
{
"value" : "0",
"dateTime" : "2018-05-17"
}
]
}
现在这仍然是一个笨拙的StackOverflow问题(通常你可能应该减少它,因为它只是无聊的重复,但这对于第一个问题是可以的),但它仍然更容易以这种形式消化。并且它有希望教会您如何构建Codable
结构以真正的Swifty形式表示您的数据,以及如何将一些凌乱的JSON格式化为更易读的格式,更容易用您的眼睛消化。
很明显JSON是正确的,因为JSONDecoder
设法解析它,但是当你以漂亮的印刷形式看到它时,它作为人类判断它应该是什么样子也更容易。
像这样,activity
应该很容易处理并在TableView
中使用,所以我希望至少有一些问题已经解决了。