You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift解析GeoJSON时结构体适配多类型属性问题求助

解决Swift解析混合类型GeoJSON Properties的问题

方案一:自定义枚举处理多类型属性

由于你的properties字段同时包含Int和String类型,直接使用Dictionary<String, String>会因类型不匹配导致解码失败。可以定义一个遵循Decodable的枚举,覆盖这两种数据类型:

enum PropertyValue: Decodable {
    case int(Int)
    case string(String)
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let intValue = try? container.decode(Int.self) {
            self = .int(intValue)
        } else if let stringValue = try? container.decode(String.self) {
            self = .string(stringValue)
        } else {
            throw DecodingError.typeMismatch(PropertyValue.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "不支持的PropertyValue类型"))
        }
    }
}

struct Feature: Decodable {
    let type: String
    let properties: [String: PropertyValue]
}

使用时通过枚举判断类型取值:

// 解析完成后访问属性
if case let .int(id) = feature.properties["@id"] {
    print("ID: \(id)")
}
if case let .string(building) = feature.properties["building"] {
    print("Building: \(building)")
}

方案二:定义固定结构的Properties结构体(推荐属性已知场景)

如果你的properties字段是固定的(比如仅包含@id和building),直接定义对应结构体更直观且类型安全:

struct Properties: Decodable {
    let id: Int
    let building: String
    
    // 自定义CodingKey映射@id字段名
    enum CodingKeys: String, CodingKey {
        case id = "@id"
        case building
    }
}

struct Feature: Decodable {
    let type: String
    let properties: Properties
}

若需要兼容@id可能返回字符串格式数字的情况,可以添加自定义属性包装器:

@propertyWrapper
struct DecodeableAsInt: Decodable {
    let wrappedValue: Int
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let intValue = try? container.decode(Int.self) {
            wrappedValue = intValue
        } else if let stringValue = try? container.decode(String.self), let intValue = Int(stringValue) {
            wrappedValue = intValue
        } else {
            throw DecodingError.typeMismatch(Int.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "无法将值解析为Int类型"))
        }
    }
}

修改后结构体使用属性包装器:

struct Properties: Decodable {
    @DecodeableAsInt var id: Int
    let building: String
    
    enum CodingKeys: String, CodingKey {
        case id = "@id"
        case building
    }
}

这样解析后可直接通过feature.properties.id和feature.properties.building访问对应值。


内容的提问来源于stack exchange,提问作者user18624814

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:10:50