Decoding from dictionary


#1

A common pattern in Objective-c is to convert a data model object to and from a NSDictionary<NSString *, id>. Many popular open-sourced projects like Mantle are built around this approach.

To leverage Swift's automatic decoding though, you'd first have to convert a Dictionary<String, Any?> into Data, and then use JSONDecoder. Is there something in the standard library to support a conversion directly to and from dictionary <> model? If not, does this seem appropriate to have?


(Morten Bek Ditlevsen) #2

Hi ebg,

It’s an idea that I’d very much support!
The subject has been visited before:

My own summary of the discussion is that such a StructureEncoder and StructureDecoder is something that could happen.
My own personal twist on the encoding and decoding of structures is that I would like them to behave as the current JSONDecoder and encoder with regards to the options they take (for doing automatic key conversion), but that does not sound like it’s common enough to be a desired feature.
Sincerely,
/morten


(John Scott) #3

The relevant functionality appears to already exist in JSONEncoder.swift:

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

        let decoder = _JSONDecoder(referencing: topLevel, 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
    }

Splitting decode() in half (and the same for encode()) should do the trick. I would assume that more checking of the topLevel would be needed as currently, it will only be an Array or Dictionary.

I for one would love it if it worked with more types (cough ... Date ... cough).