使用 Swift Xcode 创建 JSON 对象

Create JSON object with Swift Xcode

我下面有一个 JSON 对象,它使用了字符串、布尔值和整数的所有内容。我目前很难重新创建对象的 person_details 部分,我认为是因为它在括号中并且具有多个值,例如 [String: Bool][String: String][String: Int]

我在底部张贴了控制台上填充的内容,但是任何帮助构建 person_details 部分的内容都会很棒。 您将在下面看到,在我的订单中,我正在构建数据。

let testJson = """
{
"household": {
    "region": "PA",
    "household_size": 1,
    "receiving_benefits": [
    ],
    "energy_crisis": false,
    "utility_providers": [
        "peco"
    ],
    "residence_type": "other",
    "property_tax_past_due": false,
    "home_needs_repairs": false,
    "filed_previous_year_tax_return": false,
    "heating_system_needs_repairs": false,
    "at_risk_of_homelessness": false,
    "received_maximum_benefit": {
        "cip": false
    },
    "person_details": [
        {
            "age": 18,
            "marital_status": "single",
            "minimum_employment_over_extended_period": false,
            "work_status": "recent_loss",
            "pregnant": false,
            "attending_school": false,
            "disabled": false
        }
    ],
    "incomes": [
        {
            "gross_monthly_amount": 700,
            "countable_group": "household",
            "year": "current"
        },
        {
            "gross_monthly_amount": 700,
            "countable_group": "household",
            "year": "previous"
        }
    ],
    "assets": [
        {
            "amount": 1000,
            "countable_group": "household"
        }
    ]
}
}
"""

struct Eligibility: Encodable {
    let residence: String
    let hhmembers: Int
    let receivingBen: [String]
    let unhoused: Bool
    let utilityType: [String]
    let residenceType: String
    let propertyTax: Bool
    let homeRepairs: Bool
    let fileLastTax: Bool
    let heatRepairs: Bool
    let receivingMax: [String: Bool]

    enum CodingKeys: String, CodingKey {
        case residence = "region"
        case hhmembers = "household_size"
        case receivingBen = "receiving_benefits"
        case unhoused = "at_risk_of_homelessness"
        case utilityType = "utility_providers"
        case residenceType = "residence_type"
        case propertyTax = "property_tax_past_due"
        case homeRepairs = "home_needs_repairs"
        case fileLastTax = "filed_previous_year_tax_return"
        case heatRepairs = "heating_system_needs_repairs"
        case receivingMax = "received_maximum_benefit"
    }
}

struct PersonDetails: Encodable {
            let age: Int
           //  let marital_status: String
            // let minimum_employment_over_extended_period: Bool
            // let work_status: String
           //  let pregnant: Bool
            // let attending_school: Bool
           //  let disabled: Bool
    
    enum CodingKeys: String, CodingKey {
        case age = "age"
      //  case marital_status = "marital_status"
      //  case minimum_employment_over_extended_period = "minimum_employment_over_extended_period"
      //  case work_status = "work_status"
      //  case pregnant = "pregnant"
      //  case attending_school = "attending_school"
      //  case disabled = "disabled"
    }
}

我相信我缺少的是在 let order = 里面,见下文:

struct Order: Encodable {
    let household: Eligibility
    let person_details: PersonDetails
}
 
let order = Order(household: Eligibility(residence: "PA", hhmembers: 1, receivingBen: [], unhoused: false, utilityType: ["Peco"], residenceType: "other", propertyTax: false, homeRepairs: false, fileLastTax: false, heatRepairs: false, receivingMax: ["cip": false]), person_details: PersonDetails(age: 19))



let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

let orderJsonData = try! encoder.encode(order)

print(String(data: orderJsonData, encoding: .utf8)!)

控制台内部显示 person_details 在 'household' 之外,但我需要 person_details 在家庭对象内部,因为上面完整的 JSON 对象显示在问题的顶部(也请注意方括号)。下面的控制台:

{
  "household" : {
    "region" : "PA",
    "residence_type" : "other",
    "at_risk_of_homelessness" : false,
    "property_tax_past_due" : false,
    "utility_providers" : [
      "Peco"
    ],
    "home_needs_repairs" : false,
    "filed_previous_year_tax_return" : false,
    "household_size" : 1,
    "receiving_benefits" : [

    ],
    "heating_system_needs_repairs" : false,
    "received_maximum_benefit" : {
      "cip" : false
    }
  },
  "person_details" : {
    "age" : 19
  }
}

从 JSON 转换为 swift 时,您的数据层次结构错误。

应该是...

struct Order: Codable {
   let household: Household
}

struct Household: Codable {
   let personDetails: [Person]
}

struct Person: Codable {
   let age: Int
   let maritalStatus: String
   let minimumEmploymentOverExtendedPeriod: Bool
   let workStatus: String
   let pregnant: Bool
   let attendingSchool: Bool
   let disabled: Bool
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let order = try! decoder.decode(Order.self, from: Data(testJson.utf8))

returns

Person(age: 18, maritalStatus: "single", minimumEmploymentOverExtendedPeriod: false, workStatus: "recent_loss", pregnant: false, attendingSchool: false, disabled: false)]

另外值得指出的是使用 .keyDecodingStrategy 来简化从 snake case 的转换。这节省了定义 CodingKeys。显然,这仅适用于您愿意保持命名相同的情况。