Permalink
Browse files

Add convertFromCapitalized strategy, simple test

  • Loading branch information...
MaxDesiatov committed Oct 27, 2018
1 parent 73f3830 commit 6d147739c7aa52b6b6d7ec5fd0d58740397ee233
@@ -119,13 +119,24 @@ open class XMLDecoder {
///
/// - Note: Using a key decoding strategy has a nominal performance cost, as each string key has to be inspected for the `_` character.
case convertFromSnakeCase


/// Convert from "CodingKey" to "codingKey"
case convertFromCapitalized

/// 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.
/// If the result of the conversion is a duplicate key, then only one value will be present in the container for the type to decode from.
case custom((_ codingPath: [CodingKey]) -> CodingKey)

static func _convertFromCapitalized(_ stringKey: String) -> String {
guard !stringKey.isEmpty else { return stringKey }
var result = stringKey
let range = result.startIndex...result.index(after: result.startIndex)
result.replaceSubrange(range, with: result[range].lowercased())
return result
}

internal static func _convertFromSnakeCase(_ stringKey: String) -> String {
static func _convertFromSnakeCase(_ stringKey: String) -> String {
guard !stringKey.isEmpty else { return stringKey }

// Find the first non-underscore character
@@ -38,6 +38,10 @@ internal struct _XMLKeyedDecodingContainer<K : CodingKey> : KeyedDecodingContain
self.container = Dictionary(container.map {
key, value in (XMLDecoder.KeyDecodingStrategy._convertFromSnakeCase(key), value)
}, uniquingKeysWith: { (first, _) in first })
case .convertFromCapitalized:
self.container = Dictionary(container.map {
key, value in (XMLDecoder.KeyDecodingStrategy._convertFromCapitalized(key), value)
}, uniquingKeysWith: { (first, _) in first })
case .custom(let converter):
self.container = Dictionary(container.map {
key, value in (converter(decoder.codingPath + [_XMLKey(stringValue: key, intValue: nil)]).stringValue, value)
@@ -1,12 +1,63 @@
import XCTest
@testable import XMLParsing

let example = """
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship
Id="rId1"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Target="xl/workbook.xml"/>
<Relationship
Id="rId2"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
Target="docProps/app.xml"/>
<Relationship
Id="rId3"
Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
Target="docProps/core.xml"/>
</Relationships>
"""

struct Relationships: Codable {
let items: [Relationship]

enum CodingKeys: String, CodingKey {
case items = "relationship"
}
}

struct Relationship: Codable {
enum SchemaType: String, Codable {
case officeDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
case extendedProperties = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
case coreProperties = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
}

let id: String
let type: SchemaType
let target: String

enum CodingKeys: CodingKey {
case type
case id
case target
}
}

class XMLParsingTests: XCTestCase {
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
// XCTAssertEqual(XMLParsing().text, "Hello, World!")
do {
guard let data = example.data(using: .utf8) else { return }

let decoder = XMLDecoder()
decoder.keyDecodingStrategy = .convertFromCapitalized

let rels = try decoder.decode(Relationships.self, from: data)

XCTAssertEqual(rels.items[0].id, "rId1")
} catch {
XCTAssert(false, "failed to decode the example: \(error)")
}
}


0 comments on commit 6d14773

Please sign in to comment.