我尝试使用下面的代码解码json
请求是:https://public-api.nazk.gov.ua/v1/declaration/4647cd5d-5877-4606-8e61-5ac5869b71e0
struct DeclarationInfoElement: Codable {
let data: DataClass
}
struct DataClass: Codable {
let step0: Step0
let step1: Step1
}
struct Step0: Codable {
let declarationType, declarationYear1: String
}
struct Step1: Codable {
let firstname, lastname, workPost, workPlace: String
}
func fetchDeclarationDetails (with declarationID: String, completion: @escaping(DeclarationInfoElement?) -> Void) {
var hostURL = "https://public-api.nazk.gov.ua/v1/declaration/"
hostURL = hostURL + declarationID
let url = URL(string: hostURL)!
let dataTask = URLSession.shared.dataTask(with: url) {
(data, response, error) in
let jsonDecoder = JSONDecoder()
print("Trying to decode data...")
guard let data = data else { return }
do {
let declarationInfoElement = try jsonDecoder.decode(DeclarationInfoElement.self, from: data)
completion(declarationInfoElement)
print("Done successfully")
} catch {
print(error)
}
completion(nil)
}
dataTask.resume()
}
Json是:
{"id":"4647cd5d-5877-4606-8e61-5ac5869b71e0","created_date":"05.07.2018","lastmodified_date":"05.07.2018","data":{"step_0":{"declarationType":"2","declarationYearTo":"04.07.2018","declarationYearFrom":"01.01.2018"},"step_1":{"city":"[\u041a\u043e\u043d\u0444\u0456\u0434\u0435\u043d\u0446\u0456\u0439\u043d\u0430 \u0456\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0456\u044f]","region":"[\u041a\u043e\u043d\u0444\u0456\u0434\u0435\u043d\u0446\u0456\u0439\u043d\u0430 ...
..."step_16":{"empty":"\u0423 \u0441\u0443\u0431'\u0454\u043a\u0442\u0430 \u0434\u0435\u043a\u043b\u0430\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0456\u0434\u0441\u0443\u0442\u043d\u0456 \u043e\u0431'\u0454\u043a\u0442\u0438 \u0434\u043b\u044f \u0434\u0435\u043a\u043b\u0430\u0440\u0443\u0432\u0430\u043d\u043d\u044f \u0432 \u0446\u044c\u043e\u043c\u0443 \u0440\u043e\u0437\u0434\u0456\u043b\u0456."}}}
我在JSON Validator中检查了Json,它是有效的
但是我得到了错误:
尝试解码数据... dataCorrupted(Swift.DecodingError.Context(codingPath:[],debugDescription:“给定的数据不是有效的JSON。”,底层错误:可选(错误域= NSCocoaErrorDomain代码= 3840,“ JSON文本不是以数组或对象开头,并且选项为允许未设置片段。“ UserInfo = {NSDebugDescription = JSON文本不是以数组或对象开头,并且未设置允许未设置片段的选项。}))) 2712字节
找不到答案。请帮助
答案 0 :(得分:0)
在这里,我通过使用Alamofire为您创建了一个简单的示例,这是应用程序中API调用的良好做法。
我根据here的Codable
回复为您创建了struct
JSON
。
如下所示:
import Foundation
struct DeclarationInfoElement: Codable {
let id, createdDate, lastmodifiedDate: String
let data: DataClass
enum CodingKeys: String, CodingKey {
case id
case createdDate = "created_date"
case lastmodifiedDate = "lastmodified_date"
case data
}
}
struct DataClass: Codable {
let step0: Step0
let step1: Step1
let step2: [JSONAny]
let step3, step4, step5, step6: Step
let step7, step8, step9, step10: Step
let step11: Step11
let step12, step13, step14, step15: Step
let step16: Step
enum CodingKeys: String, CodingKey {
case step0 = "step_0"
case step1 = "step_1"
case step2 = "step_2"
case step3 = "step_3"
case step4 = "step_4"
case step5 = "step_5"
case step6 = "step_6"
case step7 = "step_7"
case step8 = "step_8"
case step9 = "step_9"
case step10 = "step_10"
case step11 = "step_11"
case step12 = "step_12"
case step13 = "step_13"
case step14 = "step_14"
case step15 = "step_15"
case step16 = "step_16"
}
}
struct Step0: Codable {
let declarationType, declarationYearTo, declarationYearFrom: String
}
struct Step1: Codable {
let city, region, street, country: String
let cityPath, cityType, district, lastname: String
let postCode, postType, workPost, firstname: String
let workPlace, middlename, streetType: String
let changedName: Bool
let countryPath, engPostCode, postCategory, actualStreet: String
let actualCountry, actualCityType, actualPostCode, actualStreetType: String
let engActualAddress, previousLastname, ukrActualAddress, corruptionAffected: String
let engActualPostCode, previousFirstname, previousMiddlename, responsiblePosition: String
let sameRegLivingAddress, postTypeExtendedstatus, engSameRegLivingAddress, housePartNumExtendedstatus: String
let postCategoryExtendedstatus, apartmentsNumExtendedstatus: String
enum CodingKeys: String, CodingKey {
case city, region, street, country, cityPath, cityType, district, lastname, postCode, postType, workPost, firstname, workPlace, middlename, streetType, changedName, countryPath
case engPostCode = "eng_postCode"
case postCategory
case actualStreet = "actual_street"
case actualCountry = "actual_country"
case actualCityType = "actual_cityType"
case actualPostCode = "actual_postCode"
case actualStreetType = "actual_streetType"
case engActualAddress = "eng_actualAddress"
case previousLastname = "previous_lastname"
case ukrActualAddress = "ukr_actualAddress"
case corruptionAffected
case engActualPostCode = "eng_actualPostCode"
case previousFirstname = "previous_firstname"
case previousMiddlename = "previous_middlename"
case responsiblePosition, sameRegLivingAddress
case postTypeExtendedstatus = "postType_extendedstatus"
case engSameRegLivingAddress = "eng_sameRegLivingAddress"
case housePartNumExtendedstatus = "housePartNum_extendedstatus"
case postCategoryExtendedstatus = "postCategory_extendedstatus"
case apartmentsNumExtendedstatus = "apartmentsNum_extendedstatus"
}
}
struct Step: Codable {
let empty: String
}
struct Step11: Codable {
let the1530711324488: The1530711324488
enum CodingKeys: String, CodingKey {
case the1530711324488 = "1530711324488"
}
}
struct The1530711324488: Codable {
let person: String
let rights: Rights
let iteration, objectType, sizeIncome, incomeSource: String
let sourceCitizen, otherObjectType, sourceUaLastname, sourceEngFullname: String
let sourceUaFirstname, sourceUkrFullname, sourceUaMiddlename, sourceUaCompanyCode: String
let sourceUaCompanyName, sourceEngCompanyCode, sourceEngCompanyName, sourceUkrCompanyName: String
let objectTypeExtendedstatus, sizeIncomeExtendedstatus, sourceEngCompanyAddress, sourceUkrCompanyAddress: String
let incomeSourceExtendedstatus, sourceCitizenExtendedstatus, otherObjectTypeExtendedstatus, sourceUaSameRegLivingAddress: String
let sourceUaCompanyCodeExtendedstatus, sourceUaCompanyNameExtendedstatus: String
enum CodingKeys: String, CodingKey {
case person, rights, iteration, objectType, sizeIncome, incomeSource
case sourceCitizen = "source_citizen"
case otherObjectType
case sourceUaLastname = "source_ua_lastname"
case sourceEngFullname = "source_eng_fullname"
case sourceUaFirstname = "source_ua_firstname"
case sourceUkrFullname = "source_ukr_fullname"
case sourceUaMiddlename = "source_ua_middlename"
case sourceUaCompanyCode = "source_ua_company_code"
case sourceUaCompanyName = "source_ua_company_name"
case sourceEngCompanyCode = "source_eng_company_code"
case sourceEngCompanyName = "source_eng_company_name"
case sourceUkrCompanyName = "source_ukr_company_name"
case objectTypeExtendedstatus = "objectType_extendedstatus"
case sizeIncomeExtendedstatus = "sizeIncome_extendedstatus"
case sourceEngCompanyAddress = "source_eng_company_address"
case sourceUkrCompanyAddress = "source_ukr_company_address"
case incomeSourceExtendedstatus = "incomeSource_extendedstatus"
case sourceCitizenExtendedstatus = "source_citizen_extendedstatus"
case otherObjectTypeExtendedstatus = "otherObjectType_extendedstatus"
case sourceUaSameRegLivingAddress = "source_ua_sameRegLivingAddress"
case sourceUaCompanyCodeExtendedstatus = "source_ua_company_code_extendedstatus"
case sourceUaCompanyNameExtendedstatus = "source_ua_company_name_extendedstatus"
}
}
struct Rights: Codable {
let the1: [String: String]
enum CodingKeys: String, CodingKey {
case the1 = "1"
}
}
// MARK: Encode/decode helpers
class JSONNull: Codable {
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
class JSONCodingKey: CodingKey {
let key: String
required init?(intValue: Int) {
return nil
}
required init?(stringValue: String) {
key = stringValue
}
var intValue: Int? {
return nil
}
var stringValue: String {
return key
}
}
class JSONAny: Codable {
let value: Any
static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError {
let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny")
return DecodingError.typeMismatch(JSONAny.self, context)
}
static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError {
let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny")
return EncodingError.invalidValue(value, context)
}
static func decode(from container: SingleValueDecodingContainer) throws -> Any {
if let value = try? container.decode(Bool.self) {
return value
}
if let value = try? container.decode(Int64.self) {
return value
}
if let value = try? container.decode(Double.self) {
return value
}
if let value = try? container.decode(String.self) {
return value
}
if container.decodeNil() {
return JSONNull()
}
throw decodingError(forCodingPath: container.codingPath)
}
static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any {
if let value = try? container.decode(Bool.self) {
return value
}
if let value = try? container.decode(Int64.self) {
return value
}
if let value = try? container.decode(Double.self) {
return value
}
if let value = try? container.decode(String.self) {
return value
}
if let value = try? container.decodeNil() {
if value {
return JSONNull()
}
}
if var container = try? container.nestedUnkeyedContainer() {
return try decodeArray(from: &container)
}
if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self) {
return try decodeDictionary(from: &container)
}
throw decodingError(forCodingPath: container.codingPath)
}
static func decode(from container: inout KeyedDecodingContainer<JSONCodingKey>, forKey key: JSONCodingKey) throws -> Any {
if let value = try? container.decode(Bool.self, forKey: key) {
return value
}
if let value = try? container.decode(Int64.self, forKey: key) {
return value
}
if let value = try? container.decode(Double.self, forKey: key) {
return value
}
if let value = try? container.decode(String.self, forKey: key) {
return value
}
if let value = try? container.decodeNil(forKey: key) {
if value {
return JSONNull()
}
}
if var container = try? container.nestedUnkeyedContainer(forKey: key) {
return try decodeArray(from: &container)
}
if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) {
return try decodeDictionary(from: &container)
}
throw decodingError(forCodingPath: container.codingPath)
}
static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any] {
var arr: [Any] = []
while !container.isAtEnd {
let value = try decode(from: &container)
arr.append(value)
}
return arr
}
static func decodeDictionary(from container: inout KeyedDecodingContainer<JSONCodingKey>) throws -> [String: Any] {
var dict = [String: Any]()
for key in container.allKeys {
let value = try decode(from: &container, forKey: key)
dict[key.stringValue] = value
}
return dict
}
static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws {
for value in array {
if let value = value as? Bool {
try container.encode(value)
} else if let value = value as? Int64 {
try container.encode(value)
} else if let value = value as? Double {
try container.encode(value)
} else if let value = value as? String {
try container.encode(value)
} else if value is JSONNull {
try container.encodeNil()
} else if let value = value as? [Any] {
var container = container.nestedUnkeyedContainer()
try encode(to: &container, array: value)
} else if let value = value as? [String: Any] {
var container = container.nestedContainer(keyedBy: JSONCodingKey.self)
try encode(to: &container, dictionary: value)
} else {
throw encodingError(forValue: value, codingPath: container.codingPath)
}
}
}
static func encode(to container: inout KeyedEncodingContainer<JSONCodingKey>, dictionary: [String: Any]) throws {
for (key, value) in dictionary {
let key = JSONCodingKey(stringValue: key)!
if let value = value as? Bool {
try container.encode(value, forKey: key)
} else if let value = value as? Int64 {
try container.encode(value, forKey: key)
} else if let value = value as? Double {
try container.encode(value, forKey: key)
} else if let value = value as? String {
try container.encode(value, forKey: key)
} else if value is JSONNull {
try container.encodeNil(forKey: key)
} else if let value = value as? [Any] {
var container = container.nestedUnkeyedContainer(forKey: key)
try encode(to: &container, array: value)
} else if let value = value as? [String: Any] {
var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key)
try encode(to: &container, dictionary: value)
} else {
throw encodingError(forValue: value, codingPath: container.codingPath)
}
}
}
static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws {
if let value = value as? Bool {
try container.encode(value)
} else if let value = value as? Int64 {
try container.encode(value)
} else if let value = value as? Double {
try container.encode(value)
} else if let value = value as? String {
try container.encode(value)
} else if value is JSONNull {
try container.encodeNil()
} else {
throw encodingError(forValue: value, codingPath: container.codingPath)
}
}
public required init(from decoder: Decoder) throws {
if var arrayContainer = try? decoder.unkeyedContainer() {
self.value = try JSONAny.decodeArray(from: &arrayContainer)
} else if var container = try? decoder.container(keyedBy: JSONCodingKey.self) {
self.value = try JSONAny.decodeDictionary(from: &container)
} else {
let container = try decoder.singleValueContainer()
self.value = try JSONAny.decode(from: container)
}
}
public func encode(to encoder: Encoder) throws {
if let arr = self.value as? [Any] {
var container = encoder.unkeyedContainer()
try JSONAny.encode(to: &container, array: arr)
} else if let dict = self.value as? [String: Any] {
var container = encoder.container(keyedBy: JSONCodingKey.self)
try JSONAny.encode(to: &container, dictionary: dict)
} else {
var container = encoder.singleValueContainer()
try JSONAny.encode(to: &container, value: self.value)
}
}
}
您的API调用将是:
Alamofire.request("https://public-api.nazk.gov.ua/v1/declaration/4647cd5d-5877-4606-8e61-5ac5869b71e0").responseData { response in
switch response.result {
case .success(let data):
let declarationInfoElement = try? JSONDecoder().decode(DeclarationInfoElement.self, from: data)
print(declarationInfoElement)
case .failure:
print("fail")
}
}
here是演示项目。希望这会有所帮助。