1

I want to combine 3 json results into one for looping into later.

I have tried every single combination on the internet yet I'm still stuck a dead end. I am calling an API call that in response, receives json data. I want to get the first 3 results and return that data to the calling method however, I just cannot find a way to find the desired response.

var data: JSON = []

func getData(forKey url: URL, completion: @escaping ([JSON]) -> Void){

        AF.request(url).responseJSON { (responseData) -> Void in
            if((responseData.result.value) != nil) {
                let swiftyJsonVar = JSON(responseData.result.value!)
                for loopID in 0 ... 2{
                    print(swiftyJsonVar["results"][loopID])
                }
            }
            return completion([self.data])
        }
    }

My desired results are

[
    {
        "name": "james",
        "location": "Mars"
    },
    {
        "name": "james",
        "location": "Mars"
    },
    {
        "name": "james",
        "location": "Mars"
    }
]

When, in my loop, I receive, x 3

{
    "name": "james",
    "location": "Mars"
}

1 Answer 1

1

For starters, I'd put in a breakpoint and see what your response object looks like from whatever endpoint you're hitting. Perhaps those really are the first three elements of the array?

Moving along to the matter at hand, I would use the Codable protocol for decoding your response. I'll skip the Alamofire part and focus solely on decoding the object. Using your example, here's what the struct would look like:

struct ResponseObject: Codable {
    let name: String
    let location: String
}

I would avoid using the bang operator (!) in your code, as you'll throw an exception if you tell the compiler it's 100% guaranteed money in the bank the object's not nil and it actually is. Instead, unwrap optionals.

You'll need a landing spot for your decoded data, so you could declare an empty array of responses, as follows:

var arrayOfObjects: [ResponseObject] = []

Then, you'd just declare a decoder and decode your data:

let decoder = JSONDecoder()

do {
    if let data = rawData {
        arrayOfObjects = try decoder.decode([ResponseObject].self, from: data)
        print("number of objects:", arrayOfObjects.count)
        let slice = arrayOfObjects.prefix(3)
        arrayOfObjects = Array(slice)
        print("number of objects after slicing the array:", arrayOfObjects.count)
    }
} catch {
    print(error)
}

Instead of looping through the array, just grab the first three elements of the array with .prefix(3). Fiddling with this just now, I tried prefixing the first 10 elements of an array with 4 and it didn't generate an exception, so I think that should work without checking the count of the array first.

I would suggest taking a look through Swift documentation online re: Arrays or you could get a pretty sweet Mac OS app called Dash that lets you load up docsets for a bunch of languages on your machine locally.

Good luck!

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

3 Comments

Initializer for conditional binding must have Optional type, not 'JSON' where it says ``` let data = rawData``` -- I changed rawData to my response JSON.
@JamesB you already checked rawData while declaration using guard. Just remove if let data = rawData { } condition and replace data with rawData
@HarshalWani Nothing I try works. I use the responseData which just results in this error: Cannot convert value of type 'DataResponse<Any>' to expected argument type 'Data'

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.