2017-08-20 39 views
1

我想从一个http资源解析一个json(这是我的路由器,所以http是强制性的)。json swift4如何设置结构?

后,我设置Info.plistApp Security Transport是我得到我得到 1尝试的数据连接:

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 { $0.map { $0} } 
     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的。

+0

您的代码似乎更更复杂,它必须这样做。使用Swift 4进行JSON解码可以非常简单。你可以发布你的数据模型和完整的JSON到你的问题吗? –

+0

请发布原始JSON,你发布的内容无效。 – nathan

回答

1

假设这是你打算粘贴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) 
+0

据我所知,你在varvalue中设置了一个字符串和一个数组,并用enum“any”来捕获它。然后双击检查if语句elementValue。 2个问题。你会不会在快速3中做同样的事情? 对我来说第二个接缝在那个特殊情况下没有swift 4的好处我是吗? – HongKongTom

+0

Codable在Swift 4中引入 – nathan

+0

你是对的。所以我的错误是不设置枚举“或者”,并让它通过每个键,每个按键。这是因为解码只能自动处理int和string而没有数组。我只是想了解我的思想错误在哪里。如果您观看该视频,它看起来非常容易https://www.youtube.com/watch?v=YY3bTxgxWss,甚至没有init的东西。 – HongKongTom