In Swift, how to serialize an arbitrary object in Toml format?

209 Views Asked by At

Thanks for your help. I need interaction with Toml files in my macOS Swift application. I am using the TOMLDecoder library to parse the Toml format. The library works by specifying a Swift struct type that conforms to Codable, and have the library create the object for us. From the docs:

struct Discography: Codable {
    struct Album: Codable {
       let name: String
       struct Song: Codable {
          let name: String
       }
       let songs: [Song]
    }
    let albums: [Album]
}

If we take a sample Toml file:

[[albums]]
name = "Born to Run"

    [[albums.songs]]
    name = "Jungleland"

    [[albums.songs]]
    name = "Meeting Across the River"

[[albums]]
name = "Born in the USA"

  [[albums.songs]]
  name = "Glory Days"

  [[albums.songs]]
  name = "Dancing in the Dark"

We can parse it with:

let tomlData = try? Data(contentsOf: URL(fileURLWithPath: "/path/to/file"))
let discography = try? TOMLDecoder().decode(Discography.self, from: tomlData)

Here comes my question. The library does not provide a way to reverse the process, so to serialize back the object, so I would like to write that on my own, and, possibly, I would like to achieve a solution in clean Swift, if I understand correctly, by the use of the T type, thus allowing any kind of Codable conforming object to be serializable. The decode function in the library is:

public func decode<T: Decodable>(_ type: T.Type, from text: String) throws -> T {
    let topLevel: Any
    do {
        topLevel = try TOMLDeserializer.tomlTable(with: text)
    } catch {
        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid TOML.", underlyingError: error))
    }

    let decoder = TOMLDecoderImpl(referencing: self, options: self.options)
    guard let value = try decoder.unbox(topLevel, as: type) else {
        throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
    }

    return value
}

I have started to write my encode function like the following:

class TOMLEncoder: TOMLDecoder {

    func encode<T>(sourceObject: T) -> String {
    
        return "Sample serialized text..."
    
    }

}

I really don't know how to proceed... from my very limited knowledge I should iterate somehow on the sourceObject properties and create the TOML file from the contents of those properties, but I am not sure if that is the correct approach and how to achieve it. Any help is greatly appreciated. Thanks

0

There are 0 best solutions below