Home > database >  Create JSON object with Swift Xcode
Create JSON object with Swift Xcode

Time:03-07

I have a JSON object below that uses everything from Strings, Bools and Int's. I'm currently having a difficult time recreating the person_details section of the object and I think because it's in brackets and has multiple values, like [String: Bool], [String: String] & [String: Int] ?

I posted towards the bottom what populates on the console, but any help structuring there person_details section in the would be great. You'll see below, in my let order, I'm structuring the data.

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"
    }
}

I believe What I'm missing is inside the let order = , see below:

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)!)

Inside the Console shows that person_details in outside of 'household' but I would need the person_details inside of the household object as the above full JSON object shows at the top of the question (note square brackets too). Console below:

{
  "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
  }
}

CodePudding user response:

You've got the structure of your data hierarchy wrong converting from JSON to swift.

It should be...

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)]

Also worth pointing out is the use of the .keyDecodingStrategy to ease the converting from snake case. This saves defining the CodingKeys. Obviously this will only work where you're happy to keep the naming the same.

  • Related