Search code examples
jsonswiftgenericstypesdecode

Decode websocket message (JSON string) to Swift object depending on JSON field value?


in common case you know what type do you need to decode. For example:

func decode<T: Decodable>(_ result: Result<Response, MoyaError>) -> Result<T, Error> {
  let nResult = Result {
    try JSONDecoder().decode(T.self, from: data)
  }
  return nResult
}

Before calling of decode you know which type you need.

But what if T depends on json contents? For example, json contains field "type". It is ok to use switch-case to choose the appropriate class but how to get this "type" value correctly? Should I decode json twice - to get type and to convert to the object I need?


Solution

  • First you need to create model with the field value:

    enum FieldValues: String, Decodable {
        case one, two, three
    }
    
    struct ResponseTypeModel: Decodable {
       let fieldName: FieldValues
    }
    

    Then you can decode it depending on this field:

    let type = try JSONDecoder().decode(ResponseTypeModel.self, from: data)
    switch type.fieldName {
    case .one:
       let result = try JSONDecoder().decode(FirstModel.self, from: data)
    case two:
       let result = try JSONDecoder().decode(SecondModel.self, from: data)
    case three:
       let result = try JSONDecoder().decode(ThirdModel.self, from: data)
    }