Search code examples
jsonswiftencodable

What is the most elegant way to create nested json using swift 4?


What is the most elegant way to create JSON from this structure with the only one parameter

    struct SessionStorage: Encodable {
        var value: String

        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
        /// the magic
        }

        enum CodingKeys: String, CodingKey {
            case params
        }
    }

into this JSON-string?

{"params": {"value": "{value}"}}

I don't want to create nested structs.


Solution

  • Two ways:

    1. Encode the dictionary as [String: SessionStorage]

      struct SessionStorage: Encodable {
          var value: String
      }
      
      let session = SessionStorage(value: "Foo")
      
      do {
          let jsonData = try JSONEncoder().encode(["params" : session])
          print(String(data: jsonData, encoding: .utf8)!)
      } catch { print(error) }
      
    2. Use an envelope struct

      struct Envelope : Encodable {
          let params : SessionStorage
      }
      
      
      struct SessionStorage: Encodable {
          var value: String
      }
      
      let envelope = Envelope(params : SessionStorage(value: "Foo"))
      
      do {
          let jsonData = try JSONEncoder().encode(envelope)
          print(String(data: jsonData, encoding: .utf8)!)
      } catch { print(error) }
      

    IMHO it's not a question of elegance, it's a question of efficiency. The elegance lies in not to specify encode(to and CodingKeys 😉