thoughtbot/Argo

Convert all wrong type return JSON to specific type

wongzigii opened this issue · 6 comments

Say I am facing this situation: The server might somehow return a wrong type, eg, Int,

How can I force cast the wrong Int type into the correct String type?

In my case, I will get an typeMismatch error, when running into the second decoded object.

Error Messages

List all the error messages or warnings you are seeing, if any.

Sample JSON

{"result": 
[
    {
      "title": "Title1",
      "balance": "1234" // or somehow might be 1234
    },
    {
      "title": "Title2",
      "balance": 1234
    }
]}

Models

All models involved, including their Decodable implementations.

struct User {
  title: String,
  balance: String
}

extension User: Decodable {
  // ...
}

Argo Version

_example: Argo 4.1.2

Dependency Manager

examples: Carthage, Cocoapods, git submodules, copied code, etc.

Ideally this shouldn't happen. If you control the API you should definitely try to ensure that objects are sent back with a consistent type for a specific key.

That being said: You can handle this on the client side by leveraging Alternative. In your case, if you want to store the result as a String, it's fairly straightforward because you don't need to handle potential failures when converting to Int. Maybe something like:

// this can be put wherever you want, based on preference
extension Int {
  static func toString(_ int: Int) -> String {
    return "\(int)"
  }
}

extension User: Argo.Decodable {
  static func decode(_ json: JSON) -> Decoded<User> {
    return curry(User.init)
      <^> json <| "title"
      <*> (json <| "balance") <|> (json <| "balance).map(Int.toString)
  }
}

FWIW, you could use String.init(describing:) too:

(json <| "balance").map(String.init)

oh yeah right sure

Closing now. Thanks!

@gfontenot Oh I just figure out the alternative operator <|> need to wrap a parenthesis to work around. 👍

Ah, yeah, I still don't have a great mental-model for the operator precedence (which is why I'm proposing removing some of them)