Re: [swift-evolution] JSONEncoder: Key strategies
Hi Itai, I see. I thought that the second reason you mentioned is so reasonable. Apart from this proposal, if enum with String as RawValue is defined by omitting StringLiteral, it would be a good idea to have a mechanism to generate snake_case or a space delimited string. 2017-11-08 2:20 GMT+09:00 Itai Ferber : > Hi Norio, > > There are two reasons that I think this is valuable over doing something > in CodingKeys: > >1. The definition you give your coding keys affects all encoding >formats. JSON is a format where snake_case can be relatively common, so the >transformation makes a lot of sense there. For other formats, like plist >files or otherwise, the transformation might not make as much sense. >Instead of affecting all of your coding keys globally, this limits it to >JSON. >2. More importantly, this allows you to transform keys of things which >you don’t necessarily own. If you’re working with types that you didn’t >write (but which are expected to have snake_case keys nonetheless), this >allows you to perform that transformation. If this were instead an >annotation on CodingKeys directly, you wouldn’t be able to perform it >on types you don’t directly own. > > — Itai > > On 6 Nov 2017, at 17:39, Norio Nomura via swift-evolution wrote: > > Hi Tony, > > Is it better for us to choose on `Codable` side whether `rawValue` of > `CodingKeys` should be generated with snake_case? > It seems to be more consistent with the current method of setting > `rawValue` of `CodingKeys` on `Codable` side. > > Thanks, > -- > @norio_nomura > > 2017-11-07 5:54 GMT+09:00 Tony Parker via swift-evolution < > swift-evolution@swift.org>: > >> Hi everyone, >> >> While we have no formal process at this time for proposals of changes to >> Foundation-only code, I would still like to post one that we have run >> through our internal process here for additional public comment. >> >> Link to PR with proposal content: >> >> https://github.com/apple/swift-corelibs-foundation/pull/1301 >> >> Link to implementation for the overlay: >> >> https://github.com/apple/swift/pull/12779 >> >> Markdown follows. >> >> Thanks, >> - Tony >> >> # Key Strategies for JSONEncoder and JSONDecoder >> >> * Proposal: SCLF-0001 >> * Author(s): Tony Parker >> >> # Related radars or Swift bugs >> >> * Snake case / Camel case conversions for >> JSONEncoder/Decoder >> >> # Revision history >> >> * **v1** Initial version >> >> ## Introduction >> >> While early feedback for `JSONEncoder` and `JSONDecoder` has been very >> positive, many developers have told us that they would appreciate a >> convenience for converting between `snake_case_keys` and `camelCaseKeys` >> without having to manually specify the key values for all types. >> >> ## Proposed solution >> >> `JSONEncoder` and `JSONDecoder` will gain new strategy properties to >> allow for conversion of keys during encoding and decoding. >> >> ```swift >> class JSONDecoder { >> /// The strategy to use for automatically changing the value of keys >> before decoding. >> public enum KeyDecodingStrategy { >> /// Use the keys specified by each type. This is the default >> strategy. >> case useDefaultKeys >> >> /// Convert from "snake_case_keys" to "camelCaseKeys" before >> attempting to match a key with the one specified by each type. >> /// >> /// The conversion to upper case uses `Locale.system`, also known >> as the ICU "root" locale. This means the result is consistent regardless of >> the current user's locale and language preferences. >> /// >> /// Converting from snake case to camel case: >> /// 1. Capitalizes the word starting after each `_` >> /// 2. Removes all `_` >> /// 3. Preserves starting and ending `_` (as these are often used >> to indicate private variables or other metadata). >> /// For example, `one_two_three` becomes `oneTwoThree`. >> `_one_two_three_` becomes `_oneTwoThree_`. >> /// >> /// - Note: Using a key decoding strategy has a nominal >> performance cost, as each string key has to be inspected for the `_` >> character. >> case convertFromSnakeCase >> >> /// Provide a custom conversion from the key in the encoded JSON >> to the keys specified by the decoded types. >> /// The fu
Re: [swift-evolution] JSONEncoder: Key strategies
Hi Tony, Is it better for us to choose on `Codable` side whether `rawValue` of `CodingKeys` should be generated with snake_case? It seems to be more consistent with the current method of setting `rawValue` of `CodingKeys` on `Codable` side. Thanks, -- @norio_nomura 2017-11-07 5:54 GMT+09:00 Tony Parker via swift-evolution < swift-evolution@swift.org>: > Hi everyone, > > While we have no formal process at this time for proposals of changes to > Foundation-only code, I would still like to post one that we have run > through our internal process here for additional public comment. > > Link to PR with proposal content: > > https://github.com/apple/swift-corelibs-foundation/pull/1301 > > Link to implementation for the overlay: > > https://github.com/apple/swift/pull/12779 > > Markdown follows. > > Thanks, > - Tony > > # Key Strategies for JSONEncoder and JSONDecoder > > * Proposal: SCLF-0001 > * Author(s): Tony Parker > > # Related radars or Swift bugs > > * Snake case / Camel case conversions for > JSONEncoder/Decoder > > # Revision history > > * **v1** Initial version > > ## Introduction > > While early feedback for `JSONEncoder` and `JSONDecoder` has been very > positive, many developers have told us that they would appreciate a > convenience for converting between `snake_case_keys` and `camelCaseKeys` > without having to manually specify the key values for all types. > > ## Proposed solution > > `JSONEncoder` and `JSONDecoder` will gain new strategy properties to allow > for conversion of keys during encoding and decoding. > > ```swift > class JSONDecoder { > /// The strategy to use for automatically changing the value of keys > before decoding. > public enum KeyDecodingStrategy { > /// Use the keys specified by each type. This is the default > strategy. > case useDefaultKeys > > /// Convert from "snake_case_keys" to "camelCaseKeys" before > attempting to match a key with the one specified by each type. > /// > /// The conversion to upper case uses `Locale.system`, also known > as the ICU "root" locale. This means the result is consistent regardless of > the current user's locale and language preferences. > /// > /// Converting from snake case to camel case: > /// 1. Capitalizes the word starting after each `_` > /// 2. Removes all `_` > /// 3. Preserves starting and ending `_` (as these are often used > to indicate private variables or other metadata). > /// For example, `one_two_three` becomes `oneTwoThree`. > `_one_two_three_` becomes `_oneTwoThree_`. > /// > /// - Note: Using a key decoding strategy has a nominal > performance cost, as each string key has to be inspected for the `_` > character. > case convertFromSnakeCase > > /// Provide a custom conversion from the key in the encoded JSON > to the keys specified by the decoded types. > /// The full path to the current decoding position is provided for > context (in case you need to locate this key within the payload). The > returned key is used in place of the last component in the coding path > before decoding. > case custom(([CodingKey]) -> CodingKey) > } > > /// The strategy to use for decoding keys. Defaults to > `.useDefaultKeys`. > open var keyDecodingStrategy: KeyDecodingStrategy = .useDefaultKeys > } > > class JSONEncoder { > /// The strategy to use for automatically changing the value of keys > before encoding. > public enum KeyEncodingStrategy { > /// Use the keys specified by each type. This is the default > strategy. > case useDefaultKeys > > /// Convert from "camelCaseKeys" to "snake_case_keys" before > writing a key to JSON payload. > /// > /// Capital characters are determined by testing membership in > `CharacterSet.uppercaseLetters` and `CharacterSet.lowercaseLetters` > (Unicode General Categories Lu and Lt). > /// The conversion to lower case uses `Locale.system`, also known > as the ICU "root" locale. This means the result is consistent regardless of > the current user's locale and language preferences. > /// > /// Converting from camel case to snake case: > /// 1. Splits words at the boundary of lower-case to upper-case > /// 2. Inserts `_` between words > /// 3. Lowercases the entire string > /// 4. Preserves starting and ending `_`. > /// > /// For example, `oneTwoThree` becomes `one_two_three`. > `_oneTwoThree_` becomes `_one_two_three_`. > /// > /// - Note: Using a key encoding strategy has a nominal > performance cost, as each string key has to be converted. > case convertToSnakeCase > > /// Provide a custom conversion to the key in the encoded JSON > from the keys specified by the encoded types. > /// The full path to the current encoding position is provided for > context (in case you need to locate t