1
JSON link https://raw.githubusercontent.com/shimuldn/Todoey/master/file.json

JSON code

{
"report": [
     [
        {
           "name": "Delhi"
         },
        63,
        7
      ]
   ]
}

my code

struct ApiData: Codable {
    let report: [[Details]]
}
struct Details: Codable {
    let name: String
}

I want to access the value decodeData.report[0][0].name

As soon as i run the code

debugDescription: "Expected to decode Dictionary<String, Any> but found a number instead.", underlyingError: nil

When i remove

let name: String

There is no error.

I want to get the value from the key "name" and value 63

6
  • You don't have an array of Details you have a mixed array so it is let report: [[Any]] which isn't something you can use with Codable unless maybe with a custom init(from:). Is it your json, can you change the format? Commented Feb 15, 2020 at 14:52
  • What should be that 63 in your Details structure? What about 7? Commented Feb 15, 2020 at 15:01
  • @joakim-danielson i can't change the JSON. the link is just a copy. What is the good way i can use? Commented Feb 15, 2020 at 15:09
  • "If i can get the value 63 i can get value 7 also." Not using the exact same technique (it depends on the nature of the data). Will it be precisely two values here, or is the object followed by a list of values? Is there precisely one array within the report array, or are there many? Basically, what do you want your Details struct to look like? The one you've given here just has name? And how many Details structs do you expect? Commented Feb 15, 2020 at 15:14
  • It is possible to get literally decodeData.report[0][0].name for arbitrary JSON, but the code is much more complex and harder to use than building a decoder that works for a known structure of data. Commented Feb 15, 2020 at 15:17

1 Answer 1

4

First, I'm assuming this is the data structure you want. If it's not, please update the question with your expected output data structure. (report[0][0].name is fragile and awkward to use in Swift. Create a struct that matches the data you would like to have. Then decode into that struct.)

struct ApiData: Decodable {
    let report: [Details]
}

struct Details {
    let name: String
    let value1: Int
    let value2: Int
}

So each Details has exactly a name object and two integer values. And a report is a list of Details.

given that, you can hand-decode Details using a unkeyedContainer. To get the name field out, it is handy to make a helper struct:

extension Details: Decodable {
    struct NameField: Decodable {
        let name: String
    }

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.name = try container.decode(NameField.self).name
        self.value1 = try container.decode(Int.self)
        self.value2 = try container.decode(Int.self)
    }
}

Your comment notes "there is some more below name." In that case, you may want an object rather than a string here. In that case, it would look like this:

struct Person: Decodable {
    let name: String
}

struct Details {
    let person: Person
    let value1: Int
    let value2: Int
}

extension Details: Decodable {

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.person = try container.decode(Person.self)
        self.value1 = try container.decode(Int.self)
        self.value2 = try container.decode(Int.self)
    }
}

Finally, it's possible that the list of values is unbounded, and you want an array:

struct Details {
    let person: Person
    let values: [Int]
}

In that case you'd decode by extracting all the values out of the unkeyedContainer:

extension Details: Decodable {    
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.person = try container.decode(Person.self)
        var values: [Int] = []
        while !container.isAtEnd {
            values.append(try container.decode(Int.self))
        }
        self.values = values
    }
}

There are lots of ways to approach this. It all depends on how you want to use the data, and how much structure the data has.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.