[Question] Array decoding
robertodias180 opened this issue · 4 comments
robertodias180 commented
I was wondering if it possible to ignore the elements in the array that the decode fails?
gfontenot commented
Good question. By default, we perform an all-or-nothing operation when decoding an array. However, you can write your own decode function that removes failures instead. We actually export a catDecoded
function for just this purpose. Usage might look something like this:
let decodedUsers: [User] = catDecoded(j <|| "users")
In a decode operation you'd do something like:
<*> pure(catDecoded(j <|| "users"))
gfontenot commented
nope that's wrong. It's more complicated than that:
let jsonObjects: [Decoded<JSON>] = j <|| "users" // this will always succeed as long as the key is there and it contains an array of elements
let decodedUsers: [Decoded<User>] = jsonObjects.map(User.decode) // This performs the decode operation
let users: [User] = catDecoded(decodedUsers) // This removes the failures and unwraps the successes
gfontenot commented
jesus christ I'm sorry, I apparently need more coffee.
You want something like this:
func decodeArray<T: Decodable>(_ json: JSON) -> Decoded<[T]> where T.DecodedType == T {
switch json {
case let .array(a): return pure(catDecoded(a.map(T.decode)))
default: return .typeMismatch(expected: "Array", actual: value)
}
}
You'd use it with flatMap
inside a decoder like so:
<*> (j <| "users") >>- decodeArray
you might need more or less parens there, I can never remember.
robertodias180 commented
@gfontenot thanks man, that worked like a charm 😄