1

I'm currently working on a project were the provided API sadly is a hot mess. I'm encoding a Codable with several nested Types following the first solution in this medium article about Indeterminate Types with Codable in Swift. So, I'm using an enum to allow different types in my Codable Messages roughly as follows:

struct CommandBase: Encodable {
   let command: CommandType

   enum CodingKeys: String, CodingKey {
      let command = "c"
   }
}

enum CommandType: Encodable {
   case someCommand(someContainer)
   case someOtherCommand(someOtherContainer)

   func encode(to encoder: Encoder) throws {
      var container = encoder.container(keyedBy: CodingKeys.self)
      switch self {
      case .someCommand(let someContainer):
         try container.encode("something", forkey: .name)
         try container.encode(someContainer, forKey: .container)
         try container.encode("etc", forKey: .etc)
      case .someOtherCommand(let someOtherContainer):
          // about the same as above case
      }

   }  

   enum CodingKeys: String, CodingKey {
      case name
      case container
      case etc
   }

}

The problem is, as I mentioned the API I have to work with is a mess and NEEDS the json in the correct order. But for some reason the Standard JsonEncoder always puts the .container first.

This is a refactor the earlier version used several generic types and resulted in hardly readable code but the order was met.

The JsonEncoder has an outputFormatting attribute which uses a OutputFormatting type like .sortedKeys to sort the keys alphabetical. But I don't understand if and how its possible to utilize this attribute to sort a nested codable.

has anyone an idea how I could sort the encoded message like I need?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Hellcaraxe
  • 65
  • 1
  • 1
  • 5
  • 1
    I don't think you can do that with JSONEncoder, unfortunately. That's the problem with bad API. One possible workaround is to use key placeholders, e.g. `keyA`, `keyB`, `keyC`, let them sort them alphabetically and then just replace them using a dictionary in the resulting JSON. – Sulthan Apr 21 '21 at 15:19
  • Ok, as I thought. Thanks for the reply and the suggested workaround, I will try it out. – Hellcaraxe Apr 21 '21 at 15:35
  • It works! Thanks a lot! – Hellcaraxe Apr 21 '21 at 16:16

0 Answers0