首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何将Swift JSON / Dict Key camel转换为下划线而不编码?

在Swift中,可以使用Codable协议和自定义编码器来将JSON或字典中的键从驼峰式转换为下划线式,而不进行编码。下面是一个完整的解决方案:

首先,我们需要创建一个自定义的KeyEncodingStrategy枚举,用于指定键的编码策略。在这种情况下,我们将使用.convertToSnakeCase选项,它将驼峰式键转换为下划线式键。

代码语言:txt
复制
enum KeyEncodingStrategy {
    case convertToSnakeCase

    func convert(_ key: String) -> String {
        switch self {
        case .convertToSnakeCase:
            return convertToSnakeCase(key)
        }
    }

    private func convertToSnakeCase(_ key: String) -> String {
        guard !key.isEmpty else { return key }

        var convertedKey = ""
        var wasUppercase = false

        for character in key {
            if character.isUppercase {
                if !convertedKey.isEmpty && !wasUppercase {
                    convertedKey.append("_")
                }
                wasUppercase = true
            } else {
                wasUppercase = false
            }
            convertedKey.append(character.lowercased())
        }

        return convertedKey
    }
}

接下来,我们可以创建一个自定义的KeyedCodingContainer,它将使用上述的编码策略来转换键。我们需要实现KeyedDecodingContainerProtocolKeyedEncodingContainerProtocol协议中的方法。

代码语言:txt
复制
struct KeyedCodingContainer<K: CodingKey>: KeyedDecodingContainerProtocol, KeyedEncodingContainerProtocol {
    typealias Key = K

    private let container: KeyedEncodingContainer<K>
    private let keyEncodingStrategy: KeyEncodingStrategy

    init(container: KeyedEncodingContainer<K>, keyEncodingStrategy: KeyEncodingStrategy) {
        self.container = container
        self.keyEncodingStrategy = keyEncodingStrategy
    }

    // KeyedDecodingContainerProtocol methods

    var codingPath: [CodingKey] {
        return container.codingPath
    }

    func contains(_ key: K) -> Bool {
        return container.contains(key)
    }

    func decodeNil(forKey key: K) throws -> Bool {
        return try container.decodeNil(forKey: key)
    }

    func decode<T: Decodable>(_ type: T.Type, forKey key: K) throws -> T {
        return try container.decode(type, forKey: key)
    }

    func nestedContainer<NestedKey: CodingKey>(keyedBy type: NestedKey.Type, forKey key: K) throws -> KeyedDecodingContainer<NestedKey> {
        return try container.nestedContainer(keyedBy: type, forKey: key)
    }

    func nestedUnkeyedContainer(forKey key: K) throws -> UnkeyedDecodingContainer {
        return try container.nestedUnkeyedContainer(forKey: key)
    }

    func superDecoder() throws -> Decoder {
        return try container.superDecoder()
    }

    func superDecoder(forKey key: K) throws -> Decoder {
        return try container.superDecoder(forKey: key)
    }

    // KeyedEncodingContainerProtocol methods

    mutating func encodeNil(forKey key: K) throws {
        try container.encodeNil(forKey: key)
    }

    mutating func encode<T: Encodable>(_ value: T, forKey key: K) throws {
        let convertedKey = keyEncodingStrategy.convert(key.stringValue)
        try container.encode(value, forKey: K(stringValue: convertedKey)!)
    }

    mutating func nestedContainer<NestedKey: CodingKey>(keyedBy keyType: NestedKey.Type, forKey key: K) -> KeyedEncodingContainer<NestedKey> {
        return container.nestedContainer(keyedBy: keyType, forKey: key)
    }

    mutating func nestedUnkeyedContainer(forKey key: K) -> UnkeyedEncodingContainer {
        return container.nestedUnkeyedContainer(forKey: key)
    }

    mutating func superEncoder() -> Encoder {
        return container.superEncoder()
    }

    mutating func superEncoder(forKey key: K) -> Encoder {
        return container.superEncoder(forKey: key)
    }
}

现在,我们可以创建一个自定义的JSONEncoder子类,它将使用上述的KeyedCodingContainer来进行编码。

代码语言:txt
复制
class SnakeCaseJSONEncoder: JSONEncoder {
    override func encode<T>(_ value: T) throws -> Data where T : Encodable {
        userInfo[.keyEncodingStrategy] = KeyEncodingStrategy.convertToSnakeCase
        return try super.encode(value)
    }

    override func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
        let container = super.container(keyedBy: type)
        let keyEncodingStrategy = userInfo[.keyEncodingStrategy] as? KeyEncodingStrategy ?? .useDefaultKeys
        return KeyedEncodingContainer(KeyedCodingContainer(container: container, keyEncodingStrategy: keyEncodingStrategy))
    }
}

最后,我们可以使用SnakeCaseJSONEncoder来将Swift对象编码为JSON字符串,并将驼峰式键转换为下划线式键。

代码语言:txt
复制
struct Person: Codable {
    let firstName: String
    let lastName: String
    let age: Int
}

let person = Person(firstName: "John", lastName: "Doe", age: 30)

let encoder = SnakeCaseJSONEncoder()
encoder.outputFormatting = .prettyPrinted

do {
    let jsonData = try encoder.encode(person)
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
} catch {
    print(error)
}

这样,我们就可以将Swift中的JSON或字典键从驼峰式转换为下划线式,而不进行编码。请注意,这只是一个示例解决方案,您可以根据自己的需求进行修改和扩展。

腾讯云相关产品和产品介绍链接地址:

  • 腾讯云产品:https://cloud.tencent.com/product
  • 云服务器(CVM):https://cloud.tencent.com/product/cvm
  • 云数据库 MySQL 版:https://cloud.tencent.com/product/cdb-for-mysql
  • 云原生应用引擎(TKE):https://cloud.tencent.com/product/tke
  • 云存储(COS):https://cloud.tencent.com/product/cos
  • 人工智能平台(AI):https://cloud.tencent.com/product/ai
  • 物联网(IoT):https://cloud.tencent.com/product/iotexplorer
  • 移动开发(移动推送):https://cloud.tencent.com/product/umeng
  • 区块链(BCS):https://cloud.tencent.com/product/bcs
  • 元宇宙(QTS):https://cloud.tencent.com/product/qts
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券