Yes, in general, I think Codable is a poor solution for json decoding just like 
I never used NSCoding to convert JSON to and from objects.  It feels clumsy.

I found it a much better solution to add a category to NSObject that had

-(NSData*)toJSONRepresentationWithMappings:(NSDictionary*)d
+()fromJSONRepresentation:(NSData*) mappings:(NSDictionary*)d

where mappings might be { @"firstName": @"first_name", etc.... }

and was simple to write a general solution using introspection and KVC.

Codable is a limited one trick pony that would be trivial to write as a trait 
or extension if Swift provided the more profound thing - introspection and 
reflection.  A whole world of opportunities would open up with that and we 
could stop wasting time on Codable and KeyPath - neither of which is that 
useful when working with string data from the wild.

> On Oct 19, 2017, at 8:09 AM, Tony Parker via swift-evolution 
> <[email protected]> wrote:
> 
> Hi Morten,
> 
> I’ve actually been working on this same idea already and will have something 
> to propose soon.
> 
> - Tony
> 
>> On Oct 19, 2017, at 2:03 AM, Morten Bek Ditlevsen via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> Hi all,
>> At work we have just added Codable support for a whole bunch of model 
>> objects in our code base.
>> Many places we have added CodingKeys enumeration in order to convert the 
>> camel cased property names to snake case for our JSON keys.
>> As an experiment I have tried adding a KeyCodingStrategy option to a copy of 
>> the JSONEncoder and JSONDecoder implementations.
>> This is currently an enumeration with the following values
>> .original
>> .snakeCase
>> .custom((String) -> String)
>> 
>> I just extended CodingKey as follows:
>> extension CodingKey {
>>     func stringValue(with encodingStrategy: 
>> StructuralEncoder.KeyEncodingStrategy) -> String {
>>         switch encodingStrategy {
>>         case .original:
>>             return stringValue
>>         case .snakeCase:
>>             let pattern = "([a-z0-9])([A-Z])"
>>             let regex = try! NSRegularExpression(pattern: pattern, options: 
>> [])
>>             let range = NSRange(location: 0, length: 
>> stringValue.characters.count)
>>             return regex.stringByReplacingMatches(in: stringValue, options: 
>> [], range: range, withTemplate: "$1_$2").lowercased()
>>         case .custom(let t):
>>             return t(stringValue)
>>         }
>>     }
>> }
>> 
>> and then I replaced all references to key.stringValue with 
>> key.stringValue(with: self.encoder.options.keyCodingStrategy)
>> 
>> This seems to work very nicely.
>> 
>> So my question is: Do anyone else see the benefit of such an addition to the 
>> JSONEncoder and JSONDecoder?
>> 
>> The downside as I see it, is that the current CodingKeys are guaranteed to 
>> be unique by the compiler, and it would be possible to create collisions by 
>> using key name transforms.
>> Is this downside bigger than the gains?
>> 
>> One advantage is that one could argue that one CodingKey strategy may not 
>> fit all serialization mechanisms. For instance one might wish to have upper 
>> camel cased keys in Plists (just an example) and snake case in JSON. This 
>> method could easily support this, while the current CodingKeys strategy 
>> cannot...
>> 
>> Looking forward to hearing feedback.
>> 
>> Sincerely,
>> /morten
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to