thoughtbot/Argo

Cannot convert value of type 'Any' to expected argument type 'JSON'

plspalding opened this issue · 4 comments

When I am trying to parse the json and then use the decode method I get the following:

Cannot convert value of type 'Any' to expected argument type 'JSON'

let json: Any? = try? JSONSerialization.jsonObject(with: data!, options: [])
            
            if let j: Any = json {
                let user: Weather? = Weather.decode(j) // This line is causing the issue.
            }

JSON

{"coord":{"lon":139,"lat":35},
"sys":{"country":"JP","sunrise":1369769524,"sunset":1369821049},
"weather":[{"id":804,"main":"clouds","description":"overcast clouds","icon":"04n"}],
"main":{"temp":289.5,"humidity":89,"pressure":1013,"temp_min":287.04,"temp_max":292.04},
"wind":{"speed":7.31,"deg":187.002},
"rain":{"3h":0},
"clouds":{"all":92},
"dt":1369824698,
"id":1851632,
"name":"Shuzenji",
"cod":200}

Models

Here are my structs and decodable methods:

import Foundation

import Argo
import Curry
import Runes

struct Weather {
    let rain: String
    let wind: Wind
}

struct Wind {
    let speed: Double
    let deg: Double
}

extension Weather: Decodable {
    static func decode(_ json: JSON) -> Decoded<Weather> {
        return curry(Weather.init)
            <^> json <| "rain"
            <*> json <| "wind"
    }
}

extension Wind: Decodable {
    static func decode(_ json: JSON) -> Decoded<Wind> {
        return curry(Wind.init)
            <^> json <| "speed"
            <*> json <| "deg"
    }
}

Argo Version

Argo (4.1.2)

Dependency Manager

Cocoapods

Many thanks in advance.

Not tested this, so fingers crossed! I think the problem is that you should have used the decode function rather than the static method on Weather. I think this should do it:

let json: Any? = try? JSONSerialization.jsonObject(with: data!, options: [])
            
   if let j: Any = json {
       let user: Weather? = decode(j)
   }

Thanks for the response. I was unable to get this working still. However I went with the following which did work:

let json: Any? = try? JSONSerialization.jsonObject(with: data!, options: [])
            
   if let j: Any = json {
       let user: Decoded<Weather> = decode(j)
   }

so instead of
let user: Weather? = decode(j) // With this option it couldn't find the decode method.
I use:
let user: Decoded<Weather> = decode(j)

This is strange. You can see the decode function that you should be able to use here: https://github.com/thoughtbot/Argo/blob/master/Sources/Argo/Functions/decode.swift#L79

If that's not working, you should still be able to use .value to get to the optional like so:
let user: Weather? = decode(j).value

Also, another tip to save some code space, you can eliminate the if-let by doing this:
let user: Weather? = json.flatMap(decode)
Although, if that method isn't working for you, you can try this:
let user: Weather? = json.flatMap { decode($0).value }

I'm going to go ahead and close this due to inactivity but please feel free to reopen if this is still an issue.