如何使用JSONDecoder解码自定义JSON值

时间:2018-01-30 14:42:08

标签: swift4 jsondecoder

Backend返回location的自定义JSON值。如示例所示:

=INDEX(1:1,MATCH(N5,ROUNDDOWN(INDEX(A:L,MATCH(N4,A:A,0),0),LEN(MID(N5,FIND(".",N5)+1,99))),0))

为了解析JSON我使用的是这段代码:

{
    "location": (54.000000, 21.000000)
}

当我尝试使用JSONDecoder创建Location对象时,它给出了一个错误: 给定数据无效JSON。

let json = """
{
    "location": (54.000000, 21.000000)
}
"""    
struct Location: Codable {
    var latitude: Double
    var longitude: Double
}
let dataJson = json.data(using: .utf8)!
let location = try? JSONDecoder().decode(Location.self, from: dataJson)

我知道它不是有效的JSON。 哪些方法可以覆盖我可以解析无效的JSON值?

1 个答案:

答案 0 :(得分:3)

如果第三方以一致的方式生成无效的JSON,您可以使用正则表达式将其修复回有效的JSON。 这不是万无一失的。如果JSON的格式不同,则可能会失败。最好的做法是让第三方纠正他们的后端。

您可以使用正则表达式将圆括号替换为方括号:

var json = """
{
"location": (54.000000, 21.000000)
}
"""

let regex = try! NSRegularExpression(pattern: "\\\"location\\\":\\s*\\((.+?)\\)", options: [])
let fullRange = NSRange(..<json.endIndex, in: json)

json = regex.stringByReplacingMatches(in: json, options: [], range: fullRange, withTemplate: "\"location\": [$1]")

您还需要为Location结构添加自定义解码器,因为它现在被编码为数组:

struct Location: Decodable {
    var latitude: Double
    var longitude: Double

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        latitude = try container.decode(Double.self)
        longitude = try container.decode(Double.self)
    }
}

解码示例:

struct Response: Decodable {
    var location: Location
}
let dataJson = json.data(using: .utf8)!
let location = try JSONDecoder().decode(Response.self, from: dataJson)