thoughtbot/Argo

How to decode an array of optionals in 4.X version

gorbannastya opened this issue · 2 comments

I have following JSON:

{
  "sentiment": [
    0,
    null,
    1
  ]
}

My model:

class Statistics: NSObject, NSCoding {
    typealias Sentiment = Float?
    
    let sentiment: [Sentiment]
    let emotions: [Emotion]?
    let entities: [Entity]?
    
    init(sentiment: [Sentiment], emotions: [Emotion]?, entities: [Entity]?) {
        self.sentiment = sentiment
        self.emotions = emotions
        self.entities = entities
    }

So sentiment should be parsed to array of optionals. But I cant found appropriate operator for this type of mapping.

I fond same question in closed issues #360, but seems like solution provided in this issue doesn't work with latest swift compiler. The following code doesn't compile:

extension Statistics: Decodable {
    static func decode(_ j: JSON) -> Decoded<Statistics> {
        return curry(Statistics.init)
            <^> (j <| "sentiment" >>- decodeOptionalArray)
            <*> j <||? "emotions"
            <*> j <||? "entities"
    }
}

func values<T>(xs: [Decoded<T>]) -> [T?] {
    return xs.map { $0.value }
}

func decodeOptionalArray<T: Decodable>(j: JSON) -> Decoded<[T?]> where T.DecodedType == T {
    switch j {
    case let .array(a): return pure(values(xs: a.map(T.decode)))
    default: return .typeMismatch(expected: "Array", actual: j)
    }
}

Is there other ways to parse optionals array in Argo?

Argo Version

Argo 4.1.1

Dependency Manager

Cocoapods

Hi @gorbannastya, sorry for the delay. What errors are you experiencing with that code? The code you found looks like it should work or at the very least get you close enough to be able to update the syntax to work. Did you change your model to have let sentiment: [Sentiment?]?

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