使用可编码在Swift 4中解析嵌套JSON

时间:2018-07-02 19:10:24

标签: json swift nested codable

我正在尝试在Swift 4中使用可解码的方式解析JSON

JSON如下:

{
  "_id": {
    "$oid": "5afceaa0c1743f37b4ee1cf8"
  },
  "Con_id": "xxx",
  "S_id": "xxx",
  "I_Image": [
    {
      "$binary": {
        "base64": "",
        "subType": "00"
      }
    }
  ],
  "T_Agreements": [
    {
      "Ag_Type": "xxx",
      "Ap_Type": "xxx",
      "Header": {
        "Date": {
          "$numberInt": "0"
        },
        "Company": "xxx",
        "O_Code": "xxx",
        "Lo": "xxx",
        "Completed": true
      },
      "T_Particular": {
        "C_Name": "NA",
        "C_Address": "NA",
        "C_Landline": "NA",
        "ROC": "NA",
        "T_Name": "xxx",
        "Gender": "M",
        "NR": "xxx",
        "Dob": "22/08/1977",
        "C_No": "xxx",
        "T_Address": "xxx",
        "S_No": "xxx",
        "Sign": "NA",
        "Proposed": "xxx",
        "Completed": true
      },
      "D_Agreement": {
        "C_Period": {
          "P_Yr": {
            "$numberInt": "2"
          },
          "P_Mth": {
            "$numberInt": "0"
          },
          "From": {
            "$numberInt": "0"
          },
          "To": {
            "$numberInt": "0"
          }
        },
        "First_Term": {
          "R_A": {
            "$numberInt": "800000"
          },
          "From_Date": {
            "$numberInt": "0"
          },
          "To_Date": {
            "$numberInt": "0"
          }
        },
        "Second_Term": {
          "R_A": "0",
          "From_Date": {
            "$numberInt": "0"
          },
          "To_Date": {
            "$numberInt": "0"
          }
        },
        "S_D": {
          "$numberInt": "800"
        },
        "S_D_M": {
          "$numberInt": "0"
        },
        "C_F": {
          "$numberInt": "0"
        },
        "D_C_F": {
          "$numberInt": "0"
        },
        "Maintenance_Fee": {
          "$numberInt": "0"
        },
        "Others": {
          "Description": "NA",
          "O_F": {
            "$numberInt": "0"
          }
        },
        "D_C": "NA",
        "Completed": true
      },
      "T_S": {
        "$binary": {
          "base64": "",
          "subType": "00"
        }
      },
      "L_Rep": {
        "Name": "xxx",
        "Rep_Sig": {
          "$binary": {
            "base64": "",
            "subType": "00"
          }
        }
      },
      "Remarks": ""
    }
  ],
  "Supp": {
    "B_N": "xxx",
    "B_O_H": "12",
    "C_B_O": "xxx",
    "A_S": "Nil",
    "F_T_Description": "xxx",
    "C_T": "xxx",
    "Completed": true
  },
  "FAdjustment": [
    {
      "Date": {
        "$numberInt": "0"
      },
      "R_Increased": true,
      "Pro_R": {
        "$numberInt": "20066660"
      },
      "A_P_From": {
        "$numberInt": "0"
      },
      "A_P_To": {
        "$numberInt": "0"
      },
      "E_Date": {
        "$numberInt": "0"
      },
      "A_Reason": "xxx",
      "Req": {
        "Name": "xxx",
        "Des": "xxx",
        "Sig": {
          "$binary": {
            "base64": "",
            "subType": "00"
          }
        },
        "Date": {
          "$numberInt": "0"
        }
      },
      "A1": {
        "Name": "xxx",
        "Des": "xxx",
        "Sig": {
          "$binary": {
            "base64": "",
            "subType": "00"
          }
        },
        "Date": {
          "$numberInt": "0"
        }
      },
      "A2": {
        "Name": "xxx",
        "Designation": "xxx",
        "Sig": {
          "$binary": {
            "base64": "",
            "subType": "00"
          }
        },
        "Date": {
          "$numberInt": "0"
        }
      }
    }
  ],
  "Status": "xxx",
  "Re": {
    "Out": "0"
  },
  "Termination": {
    "Terminated": false,
    "Reason": "NA"
  }
}

我可以使用Struct轻松解析诸如conID之类的内容:

struct Welcome: Codable {
    let id: ID?
    let conID, sID: String?
    let iImage: [IImage]?
    let tAgreements: [TAgreement]?
    let supp: Supp?
    let fAdjustment: [FAdjustment]?
    let status: String?
    let re: Re?
    let termination: Termination?

    enum CodingKeys: String, CodingKey {
        case id = "_id"
        case conID = "Con_id"
        case sID = "S_id"
        case iImage = "I_Image"
        case tAgreements = "T_Agreements"
        case supp = "Supp"
        case fAdjustment = "FAdjustment"
        case status = "Status"
        case re = "Re"
        case termination = "Termination"
    }
}

struct FAdjustment: Codable {
    let date: APFrom?
    let rIncreased: Bool?
    let proR, aPFrom, aPTo, eDate: APFrom?
    let aReason: String?
    let req, a1, a2: A1?

    enum CodingKeys: String, CodingKey {
        case date = "Date"
        case rIncreased = "R_Increased"
        case proR = "Pro_R"
        case aPFrom = "A_P_From"
        case aPTo = "A_P_To"
        case eDate = "E_Date"
        case aReason = "A_Reason"
        case req = "Req"
        case a1 = "A1"
        case a2 = "A2"
    }
}

struct A1: Codable {
    let name, des: String?
    let sig: IImage?
    let date: APFrom?
    let designation: String?

    enum CodingKeys: String, CodingKey {
        case name = "Name"
        case des = "Des"
        case sig = "Sig"
        case date = "Date"
        case designation = "Designation"
    }
}

struct APFrom: Codable {
    let numberInt: String?

    enum CodingKeys: String, CodingKey {
        case numberInt = "$numberInt"
    }
}

struct IImage: Codable {
    let binary: Binary?

    enum CodingKeys: String, CodingKey {
        case binary = "$binary"
    }
}

struct Binary: Codable {
    let base64, subType: String?
}

struct ID: Codable {
    let oid: String?

    enum CodingKeys: String, CodingKey {
        case oid = "$oid"
    }
}

struct Re: Codable {
    let out: String?

    enum CodingKeys: String, CodingKey {
        case out = "Out"
    }
}

struct Supp: Codable {
    let bN, bOH, cBO, aS: String?
    let fTDescription, cT: String?
    let completed: Bool?

    enum CodingKeys: String, CodingKey {
        case bN = "B_N"
        case bOH = "B_O_H"
        case cBO = "C_B_O"
        case aS = "A_S"
        case fTDescription = "F_T_Description"
        case cT = "C_T"
        case completed = "Completed"
    }
}

struct TAgreement: Codable {
    let agType, apType: String?
    let header: Header?
    let tParticular: TParticular?
    let dAgreement: DAgreement?
    let tS: IImage?
    let lRep: LRep?
    let remarks: String?

    enum CodingKeys: String, CodingKey {
        case agType = "Ag_Type"
        case apType = "Ap_Type"
        case header = "Header"
        case tParticular = "T_Particular"
        case dAgreement = "D_Agreement"
        case tS = "T_S"
        case lRep = "L_Rep"
        case remarks = "Remarks"
    }
}

struct DAgreement: Codable {
    let cPeriod: CPeriod?
    let firstTerm: FirstTerm?
    let secondTerm: SecondTerm?
    let sD, sDM, cF, dCF: APFrom?
    let maintenanceFee: APFrom?
    let others: Others?
    let dC: String?
    let completed: Bool?

    enum CodingKeys: String, CodingKey {
        case cPeriod = "C_Period"
        case firstTerm = "First_Term"
        case secondTerm = "Second_Term"
        case sD = "S_D"
        case sDM = "S_D_M"
        case cF = "C_F"
        case dCF = "D_C_F"
        case maintenanceFee = "Maintenance_Fee"
        case others = "Others"
        case dC = "D_C"
        case completed = "Completed"
    }
}

struct CPeriod: Codable {
    let pYr, pMth, from, to: APFrom?

    enum CodingKeys: String, CodingKey {
        case pYr = "P_Yr"
        case pMth = "P_Mth"
        case from = "From"
        case to = "To"
    }
}

struct FirstTerm: Codable {
    let rA, fromDate, toDate: APFrom?

    enum CodingKeys: String, CodingKey {
        case rA = "R_A"
        case fromDate = "From_Date"
        case toDate = "To_Date"
    }
}

struct Others: Codable {
    let description: String?
    let oF: APFrom?

    enum CodingKeys: String, CodingKey {
        case description = "Description"
        case oF = "O_F"
    }
}

struct SecondTerm: Codable {
    let rA: String?
    let fromDate, toDate: APFrom?

    enum CodingKeys: String, CodingKey {
        case rA = "R_A"
        case fromDate = "From_Date"
        case toDate = "To_Date"
    }
}

struct Header: Codable {
    let date: APFrom?
    let company, oCode, lo: String?
    let completed: Bool?

    enum CodingKeys: String, CodingKey {
        case date = "Date"
        case company = "Company"
        case oCode = "O_Code"
        case lo = "Lo"
        case completed = "Completed"
    }
}

struct LRep: Codable {
    let name: String?
    let repSig: IImage?

    enum CodingKeys: String, CodingKey {
        case name = "Name"
        case repSig = "Rep_Sig"
    }
}

struct TParticular: Codable {
    let cName, cAddress, cLandline, roc: String?
    let tName, gender, nr, dob: String?
    let cNo, tAddress, sNo, sign: String?
    let proposed: String?
    let completed: Bool?

    enum CodingKeys: String, CodingKey {
        case cName = "C_Name"
        case cAddress = "C_Address"
        case cLandline = "C_Landline"
        case roc = "ROC"
        case tName = "T_Name"
        case gender = "Gender"
        case nr = "NR"
        case dob = "Dob"
        case cNo = "C_No"
        case tAddress = "T_Address"
        case sNo = "S_No"
        case sign = "Sign"
        case proposed = "Proposed"
        case completed = "Completed"
    }
}

struct Termination: Codable {
    let terminated: Bool?
    let reason: String?

    enum CodingKeys: String, CodingKey {
        case terminated = "Terminated"
        case reason = "Reason"
    }
}

我正在努力把嵌套的东西拿出来。

如何从T_Agreements中获取诸如Ag_Type之类的东西,并从T_Particular中获取一切之类的东西?

我尝试过

  let jsonUrlString = "URL REMOVED REFER TO JSON ABOVE"
        guard let url = URL(string: jsonUrlString) else { return }
        URLSession.shared.dataTask(with: url) { (data, response, err) in
            guard let data = data else { return }
            do {
                let decoder = JSONDecoder()
                let welcome = try! decoder.decode(Welcome.self, from: data)
                let tagree = try! decoder.decode(TAgreement.self, from: data)

                print(tagree) // This returns all the header inside T_Agreements but the values are all nil
                print(tagree.tParticular.cAddress) // This returns nil too

            }

            }.resume()

非常感谢和赞赏

1 个答案:

答案 0 :(得分:0)

let welcome = try! decoder.decode(Welcome.self, from: data)行将json数据加载到Welcome数据模型中,该模型与json的结构匹配。尝试将相同的json数据重新加载到其他数据模型中(如您在下一行中所做的那样)将不起作用。您需要直接从创建的填充数据模型中提取数据。

要获得协议,您只需从welcome模型中获取数据:

let tagreements = welcome.tAgreements

要获取Ag_Type,请从tagreements的第一个元素中获取填充的数据:

let agType = tagreements[0].agType