json swift4如何设置struct?
json swift4 how to set the struct?
我想从 http 资源解析 json(这是我的路由器,所以 http 是必需的)。
在我设置 Info.plist
App Security Transport
之后,我确实获得了连接,我通过以下方式获取数据
第一次尝试:
let sphDataAddress = "http://speedport.ip/data/status.json"
let url = URL(string: sphDataAddress)!
let jsonData = try! Data(contentsOf: url) // ! is just for testing reason and will be in real app by guard let
print("data \(jsonData)") // shows that the received Data are 5077bytes
struct User {
let vartype: String
let varid: String
let varvalue: Company
init?(dict: [String: Any]) {
guard
let vartype = dict["vartype-data"] as? String,
let varid = dict["valid-data"] as? String,
let varvalueDict = dict["company"] as? [String: Any],
let varvalue = Company(dict: varvalueDict)
else {
return nil
}
self.vartype = vartype
self.varid = varid
self.varvalue = varvalue
}
struct Company {
let vartype: String
let varid: String
let varvalue: String
init?(dict: [String: Any]) {
guard
let vartype = dict["vartype-sub"] as? String,
let varid = dict["varid-sub"] as? String,
let varvalue = dict["varvalue-Sub"] as? String else {
return nil
}
self.vartype = vartype
self.varid = varid
self.varvalue = varvalue
}
}
}
if let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) {
if let jsonArray = json as? [[String: Any]] {
let users = jsonArray.flatMap { [=11=].map { [=11=]} }
let zun = users.count
print(users, zun)
}
}
第二次尝试:
我也试过那个但没有成功://我把它放到查看负载中只是为了测试它!!
struct RouterData: Decodable {
let vartype: String?
let varid: String?
let varvalue: String?
}
override func viewDidLoad() {
super.viewDidLoad()
let jsonUrlString = "http://speedport.ip/data/status.json"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
//perhaps check err checked by print(response)
//also perhaps check response status 200 OK
guard let data = data else { return }
do {
let courses = try JSONDecoder().decode([RouterData].self, from: data)
print(courses)
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
控制台错误:
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath:
[Foundation.(_JSONKey in
_12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 25", intValue: Optional(25)), JsonParseSwift4.RouterData.(CodingKeys in
_DD16AFBB8A755D282DC27E60A66FDC03).varvalue], debugDescription: "Expected to decode String but found an array instead.",
underlyingError: nil))
这就是来自源(路由器)
的(完整)json 结构
(
{
varid = "device_name";
vartype = value;
varvalue = "Speedport Hybrid";
},
{
varid = "provis_inet";
vartype = value;
varvalue = x03;
},
{
varid = "provis_voip";
vartype = value;
varvalue = xx3;
},
{
varid = "ppp_bnguser";
vartype = value;
varvalue = 0;
},
{
varid = bngscrat;
vartype = value;
varvalue = 0;
},
{
varid = "router_state";
vartype = value;
varvalue = OK;
},
{
varid = "support_https";
vartype = value;
varvalue = 0;
},
{
varid = title;
vartype = "page_title";
varvalue = "Speedport Hybrid Konfigurationsprogramm";
},
{
varid = onlinestatus;
vartype = status;
varvalue = online;
},
{
varid = "use_lte";
vartype = option;
varvalue = 1;
},
{
varid = "lte_status";
vartype = value;
varvalue = 10;
},
{
varid = "bonding_status";
vartype = value;
varvalue = Online;
},
{
varid = "lte_signal";
vartype = value;
varvalue = 5;
},
{
varid = loginstate;
vartype = status;
varvalue = 0;
},
{
varid = datetime;
vartype = value;
varvalue = "18.08.2017 14:54:30";
},
{
varid = "device_name";
vartype = value;
varvalue = "Speedport Hybrid";
},
{
varid = imei;
vartype = value;
varvalue = 1234567891230;
},
{
varid = "dsl_link_status";
vartype = value;
varvalue = online;
},
{
varid = "dsl_errnr";
vartype = value;
varvalue = "";
},
{
varid = status;
vartype = value;
varvalue = online;
},
{
varid = "fail_reason";
vartype = value;
varvalue = "";
},
{
varid = "inet_errnr";
vartype = value;
varvalue = "";
},
{
varid = connect;
vartype = value;
varvalue = 0;
},
{
varid = "dsl_downstream";
vartype = value;
varvalue = 8184;
},
{
varid = "dsl_upstream";
vartype = value;
varvalue = 2429;
},
{
varid = addphonenumber;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 1;
},
{
varid = "phone_number";
vartype = value;
varvalue = „*100“;
},
{
varid = failreason;
vartype = value;
varvalue = 0;
},
{
varid = status;
vartype = value;
varvalue = ok;
},
{
varid = "voip_errnr";
vartype = value;
varvalue = "";
}
);
},
{
varid = addphonenumber;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 2;
},
{
varid = "phone_number";
vartype = value;
varvalue = „*200";
},
{
varid = failreason;
vartype = value;
varvalue = 0;
},
{
varid = status;
vartype = value;
varvalue = ok;
},
{
varid = "voip_errnr";
vartype = value;
varvalue = "";
}
);
},
{
varid = addphonenumber;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 3;
},
{
varid = "phone_number";
vartype = value;
varvalue = „*300“;
},
{
varid = failreason;
vartype = value;
varvalue = 0;
},
{
varid = status;
vartype = value;
varvalue = ok;
},
{
varid = "voip_errnr";
vartype = value;
varvalue = "";
}
);
},
{
varid = adddect;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 1;
}
);
},
{
varid = adddect;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 2;
}
);
},
{
varid = adddect;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 3;
}
);
},
{
varid = "use_dect";
vartype = value;
varvalue = 1;
},
{
varid = "wlan_ssid";
vartype = value;
varvalue = Speedport;
},
{
varid = "wlan_5ghz_ssid";
vartype = value;
varvalue = Speedport5;
},
{
varid = "use_wlan";
vartype = value;
varvalue = 1;
},
{
varid = "use_wlan_5ghz";
vartype = value;
varvalue = 1;
},
{
varid = "wlan_devices";
vartype = value;
varvalue = 0;
},
{
varid = "wlan_5ghz_devices";
vartype = value;
varvalue = 3;
},
{
varid = "lan1_device";
vartype = value;
varvalue = 1;
},
{
varid = "lan2_device";
vartype = value;
varvalue = 1;
},
{
varid = "lan3_device";
vartype = value;
varvalue = 1;
},
{
varid = "lan4_device";
vartype = value;
varvalue = 1;
},
{
varid = "use_wps";
vartype = value;
varvalue = 1;
},
{
varid = "hsfon_status";
vartype = value;
varvalue = 0;
},
{
varid = "firmware_version";
vartype = value;
varvalue = "050124.03.05.017";
},
{
varid = "serial_number";
vartype = value;
varvalue = Sp123456789;
})
来自路由器的数据是:
JSON 只是一个片段,我想展示的是 varvalue
曾经是一个字符串,曾经是 []
和子数据,但 var
的。
假设这是您要粘贴的 JSON 结构:
[
{
"varid": "dsl_downstream",
"vartype": "value",
"varvalue": 11111
},
{
"varid": "adddect",
"vartype": "template",
"varvalue": [
{
"varid": "id",
"vartype": "value",
"varvalue": "some_value"
}
]
}
]
这是一个可能的解决方案:
// let jsonData = "...".data(using: .utf8)!
enum Either<A,B> where A: Decodable, B: Decodable {
case left(A)
case right(B)
}
struct RouterData: Decodable {
let type: String
let id: String
let value: Either<String,[RouterData]>
enum CodingKeys: String, CodingKey {
case type = "vartype"
case id = "varid"
case value = "varvalue"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
type = try container.decode(String.self, forKey: .type)
id = try container.decode(String.self, forKey: .id)
if let elementValue = try? container.decode(String.self, forKey: .value) {
value = .left(elementValue)
} else if let elementValue = try? container.decode(Int.self, forKey: .value) {
value = .left(String(elementValue))
} else {
let childData = try container.decode([RouterData].self, forKey: .value)
value = .right(childData)
}
}
}
let decoded = try JSONDecoder().decode([RouterData].self, from: jsonData)
print(decoded)
我想从 http 资源解析 json(这是我的路由器,所以 http 是必需的)。
在我设置 Info.plist
App Security Transport
之后,我确实获得了连接,我通过以下方式获取数据
第一次尝试:
let sphDataAddress = "http://speedport.ip/data/status.json"
let url = URL(string: sphDataAddress)!
let jsonData = try! Data(contentsOf: url) // ! is just for testing reason and will be in real app by guard let
print("data \(jsonData)") // shows that the received Data are 5077bytes
struct User {
let vartype: String
let varid: String
let varvalue: Company
init?(dict: [String: Any]) {
guard
let vartype = dict["vartype-data"] as? String,
let varid = dict["valid-data"] as? String,
let varvalueDict = dict["company"] as? [String: Any],
let varvalue = Company(dict: varvalueDict)
else {
return nil
}
self.vartype = vartype
self.varid = varid
self.varvalue = varvalue
}
struct Company {
let vartype: String
let varid: String
let varvalue: String
init?(dict: [String: Any]) {
guard
let vartype = dict["vartype-sub"] as? String,
let varid = dict["varid-sub"] as? String,
let varvalue = dict["varvalue-Sub"] as? String else {
return nil
}
self.vartype = vartype
self.varid = varid
self.varvalue = varvalue
}
}
}
if let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) {
if let jsonArray = json as? [[String: Any]] {
let users = jsonArray.flatMap { [=11=].map { [=11=]} }
let zun = users.count
print(users, zun)
}
}
第二次尝试: 我也试过那个但没有成功://我把它放到查看负载中只是为了测试它!!
struct RouterData: Decodable {
let vartype: String?
let varid: String?
let varvalue: String?
}
override func viewDidLoad() {
super.viewDidLoad()
let jsonUrlString = "http://speedport.ip/data/status.json"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
//perhaps check err checked by print(response)
//also perhaps check response status 200 OK
guard let data = data else { return }
do {
let courses = try JSONDecoder().decode([RouterData].self, from: data)
print(courses)
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
控制台错误:
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [Foundation.(_JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue: "Index 25", intValue: Optional(25)), JsonParseSwift4.RouterData.(CodingKeys in _DD16AFBB8A755D282DC27E60A66FDC03).varvalue], debugDescription: "Expected to decode String but found an array instead.", underlyingError: nil))
这就是来自源(路由器)
的(完整)json 结构 (
{
varid = "device_name";
vartype = value;
varvalue = "Speedport Hybrid";
},
{
varid = "provis_inet";
vartype = value;
varvalue = x03;
},
{
varid = "provis_voip";
vartype = value;
varvalue = xx3;
},
{
varid = "ppp_bnguser";
vartype = value;
varvalue = 0;
},
{
varid = bngscrat;
vartype = value;
varvalue = 0;
},
{
varid = "router_state";
vartype = value;
varvalue = OK;
},
{
varid = "support_https";
vartype = value;
varvalue = 0;
},
{
varid = title;
vartype = "page_title";
varvalue = "Speedport Hybrid Konfigurationsprogramm";
},
{
varid = onlinestatus;
vartype = status;
varvalue = online;
},
{
varid = "use_lte";
vartype = option;
varvalue = 1;
},
{
varid = "lte_status";
vartype = value;
varvalue = 10;
},
{
varid = "bonding_status";
vartype = value;
varvalue = Online;
},
{
varid = "lte_signal";
vartype = value;
varvalue = 5;
},
{
varid = loginstate;
vartype = status;
varvalue = 0;
},
{
varid = datetime;
vartype = value;
varvalue = "18.08.2017 14:54:30";
},
{
varid = "device_name";
vartype = value;
varvalue = "Speedport Hybrid";
},
{
varid = imei;
vartype = value;
varvalue = 1234567891230;
},
{
varid = "dsl_link_status";
vartype = value;
varvalue = online;
},
{
varid = "dsl_errnr";
vartype = value;
varvalue = "";
},
{
varid = status;
vartype = value;
varvalue = online;
},
{
varid = "fail_reason";
vartype = value;
varvalue = "";
},
{
varid = "inet_errnr";
vartype = value;
varvalue = "";
},
{
varid = connect;
vartype = value;
varvalue = 0;
},
{
varid = "dsl_downstream";
vartype = value;
varvalue = 8184;
},
{
varid = "dsl_upstream";
vartype = value;
varvalue = 2429;
},
{
varid = addphonenumber;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 1;
},
{
varid = "phone_number";
vartype = value;
varvalue = „*100“;
},
{
varid = failreason;
vartype = value;
varvalue = 0;
},
{
varid = status;
vartype = value;
varvalue = ok;
},
{
varid = "voip_errnr";
vartype = value;
varvalue = "";
}
);
},
{
varid = addphonenumber;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 2;
},
{
varid = "phone_number";
vartype = value;
varvalue = „*200";
},
{
varid = failreason;
vartype = value;
varvalue = 0;
},
{
varid = status;
vartype = value;
varvalue = ok;
},
{
varid = "voip_errnr";
vartype = value;
varvalue = "";
}
);
},
{
varid = addphonenumber;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 3;
},
{
varid = "phone_number";
vartype = value;
varvalue = „*300“;
},
{
varid = failreason;
vartype = value;
varvalue = 0;
},
{
varid = status;
vartype = value;
varvalue = ok;
},
{
varid = "voip_errnr";
vartype = value;
varvalue = "";
}
);
},
{
varid = adddect;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 1;
}
);
},
{
varid = adddect;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 2;
}
);
},
{
varid = adddect;
vartype = template;
varvalue = (
{
varid = id;
vartype = value;
varvalue = 3;
}
);
},
{
varid = "use_dect";
vartype = value;
varvalue = 1;
},
{
varid = "wlan_ssid";
vartype = value;
varvalue = Speedport;
},
{
varid = "wlan_5ghz_ssid";
vartype = value;
varvalue = Speedport5;
},
{
varid = "use_wlan";
vartype = value;
varvalue = 1;
},
{
varid = "use_wlan_5ghz";
vartype = value;
varvalue = 1;
},
{
varid = "wlan_devices";
vartype = value;
varvalue = 0;
},
{
varid = "wlan_5ghz_devices";
vartype = value;
varvalue = 3;
},
{
varid = "lan1_device";
vartype = value;
varvalue = 1;
},
{
varid = "lan2_device";
vartype = value;
varvalue = 1;
},
{
varid = "lan3_device";
vartype = value;
varvalue = 1;
},
{
varid = "lan4_device";
vartype = value;
varvalue = 1;
},
{
varid = "use_wps";
vartype = value;
varvalue = 1;
},
{
varid = "hsfon_status";
vartype = value;
varvalue = 0;
},
{
varid = "firmware_version";
vartype = value;
varvalue = "050124.03.05.017";
},
{
varid = "serial_number";
vartype = value;
varvalue = Sp123456789;
})
来自路由器的数据是:
JSON 只是一个片段,我想展示的是 varvalue
曾经是一个字符串,曾经是 []
和子数据,但 var
的。
假设这是您要粘贴的 JSON 结构:
[
{
"varid": "dsl_downstream",
"vartype": "value",
"varvalue": 11111
},
{
"varid": "adddect",
"vartype": "template",
"varvalue": [
{
"varid": "id",
"vartype": "value",
"varvalue": "some_value"
}
]
}
]
这是一个可能的解决方案:
// let jsonData = "...".data(using: .utf8)!
enum Either<A,B> where A: Decodable, B: Decodable {
case left(A)
case right(B)
}
struct RouterData: Decodable {
let type: String
let id: String
let value: Either<String,[RouterData]>
enum CodingKeys: String, CodingKey {
case type = "vartype"
case id = "varid"
case value = "varvalue"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
type = try container.decode(String.self, forKey: .type)
id = try container.decode(String.self, forKey: .id)
if let elementValue = try? container.decode(String.self, forKey: .value) {
value = .left(elementValue)
} else if let elementValue = try? container.decode(Int.self, forKey: .value) {
value = .left(String(elementValue))
} else {
let childData = try container.decode([RouterData].self, forKey: .value)
value = .right(childData)
}
}
}
let decoded = try JSONDecoder().decode([RouterData].self, from: jsonData)
print(decoded)