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.