简体   繁体   中英

Swift Decoder, trying to decode file with layers

How would I decode this json file with JSONDecoder().decode

{
  "text": "pear",
  "parsed": [
    {
      "food": {
        "foodId": "food_bq6stkiaxkwhxia9q4v7wanjnew0",
        "label": "Pear",
        "nutrients": {
          "ENERC_KCAL": 57,
          "PROCNT": 0.36,
          "FAT": 0.14,
          "CHOCDF": 15.23,
          "FIBTG": 3.1
        },
        "category": "Generic foods",
        "categoryLabel": "food",
        "image": "https://www.edamam.com/food-img/65a/65aec51d264db28bbe27117c9fdaaca7.jpg"
      }
    }
  ],
  "hints": [
    {
      "food": {
        "foodId": "food_bq6stkiaxkwhxia9q4v7wanjnew0",
        "label": "Pear",
        "nutrients": {
          "ENERC_KCAL": 57,
          "PROCNT": 0.36,
          "FAT": 0.14,
          "CHOCDF": 15.23,
          "FIBTG": 3.1
        },
        "category": "Generic foods",
        "categoryLabel": "food",
        "image": "https://www.edamam.com/food-img/65a/65aec51d264db28bbe27117c9fdaaca7.jpg"
      },
      "measures": [
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_unit",
          "label": "Whole",
          "qualified": [
            {
              "qualifiers": [
                {
                  "uri": "http://www.edamam.com/ontologies/edamam.owl#Qualifier_large",
                  "label": "large"
                }
              ]
            },
            {
              "qualifiers": [
                {
                  "uri": "http://www.edamam.com/ontologies/edamam.owl#Qualifier_small",
                  "label": "small"
                }
              ]
            },
            {
              "qualifiers": [
                {
                  "uri": "http://www.edamam.com/ontologies/edamam.owl#Qualifier_medium",
                  "label": "medium"
                }
              ]
            }
          ]
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_serving",
          "label": "Serving"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_half",
          "label": "Half"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_slice",
          "label": "Slice"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_gram",
          "label": "Gram"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_ounce",
          "label": "Ounce"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_pound",
          "label": "Pound"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_kilogram",
          "label": "Kilogram"
        },
        {
          "uri": "http://www.edamam.com/ontologies/edamam.owl#Measure_cup",
          "label": "Cup"
        }

The file goes on and on.

I try to do [String] but it says it expects a dictionary, So I put in a dictionary, then it says it expects another dictionary, This repeats until I have this:

let posts = try! JSONDecoder().decode([String: [String: [String: String]]].self, from: data!)

Then I get the error

"Expected to decode Dictionary<String, Any> but found a string/data instead.", underlyingError: nil))

Though when I go back one to do a string/data I get this error

"Expected to decode String but found a dictionary instead.", underlyingError: nil))

Help?

As mentioned in the comments you can use a quick parser , however you need to understand why is this happening, the issue here is that you're passing [String: [String: [String: String]]] which is not valid skeleton for this key you can start breaking down each layer alone to understand first level for example [String, Any] and then start exporting each key and decode that stand alone, using the above link your models should be something like that.

// MARK: - Foo
struct Foo: Codable {
    let text: String
    let parsed: [Parsed]
    let hints: [Hint]
}

// MARK: - Hint
struct Hint: Codable {
    let food: Food
    let measures: [Measure]
}

// MARK: - Food
struct Food: Codable {
    let foodID, label: String
    let nutrients: Nutrients
    let category, categoryLabel: String
    let image: String

    enum CodingKeys: String, CodingKey {
        case foodID = "foodId"
        case label, nutrients, category, categoryLabel, image
    }
}

// MARK: - Nutrients
struct Nutrients: Codable {
    let enercKcal: Int
    let procnt, fat, chocdf, fibtg: Double

    enum CodingKeys: String, CodingKey {
        case enercKcal = "ENERC_KCAL"
        case procnt = "PROCNT"
        case fat = "FAT"
        case chocdf = "CHOCDF"
        case fibtg = "FIBTG"
    }
}

// MARK: - Measure
struct Measure: Codable {
    let uri: String
    let label: String
    let qualified: [Qualified]?
}

// MARK: - Qualified
struct Qualified: Codable {
    let qualifiers: [Qualifier]
}

// MARK: - Qualifier
struct Qualifier: Codable {
    let uri: String
    let label: String
}

// MARK: - Parsed
struct Parsed: Codable {
    let food: Food
}

And you can use it simply like this:

let foo = try? newJSONDecoder().decode(Foo.self, from: jsonData)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM