简体   繁体   English

Swift JSON 可解码 \

[英]Swift JSON Decodable \u0000

Problem问题

I'm currently getting JSON from a server that I don't have access to.我目前正在从我无权访问的服务器获取 JSON。 The JSON I sometimes get will put this character \ at the end of a String.我有时得到的 JSON 会将这个字符\放在字符串的末尾。 As a result my decoding fails because this character just fails it.结果我的解码失败了,因为这个字符只是失败了。

I'm trying to debug this in Playground but I keep getting this error.我正在尝试在 Playground 中调试它,但我不断收到此错误。

Expected hexadecimal code in braces after unicode escape

Here is some sample code to try out.这是一些可以尝试的示例代码。

import UIKit
import Foundation

struct GroceryProduct: Codable {
    var name: String
}

let json = """
{
    "name": "Durian \u0000"
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let product = try decoder.decode(GroceryProduct.self, from: json)

print(product.name)

Question问题

How do you deal with \ from JSON?你如何处理来自 JSON 的\ I have been looking at DataDecodingStrategy from the Apple documentation but I can't even test anything out because the Playground fails to even run.我一直在查看 Apple 文档中的DataDecodingStrategy ,但我至无法测试任何内容,因为 Playground 甚至无法运行。

Any direction or advice would be appreciated.任何方向或建议将不胜感激。


Update更新

Here is some more setup code to tryout in your Playground or a real app.这里有更多设置代码可以在您的 Playground 或真实应用中试用。

JSON test.json JSON 测试.json

{
    "name": "Durian \u0000"
}

Code代码

extension Bundle {
    func decode<T: Decodable>(_ type: T.Type, from file: String, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> T {
        
        guard let url = self.url(forResource: file, withExtension: nil) else {
            fatalError("Failed to locate \(file) in bundle.")
        }

        guard let data = try? Data(contentsOf: url) else {
            fatalError("Failed to load \(file) from bundle.")
        }
                
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy    = .deferredToDate
        decoder.keyDecodingStrategy     = .useDefaultKeys

        do {
            return try decoder.decode(T.self, from: data)
        } catch DecodingError.keyNotFound(let key, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing key '\(key.stringValue)' not found – \(context.debugDescription)")
        } catch DecodingError.typeMismatch(_, let context) {
            fatalError("Failed to decode \(file) from bundle due to type mismatch – \(context.debugDescription)")
        } catch DecodingError.valueNotFound(let type, let context) {
            fatalError("Failed to decode \(file) from bundle due to missing \(type) value – \(context.debugDescription)")
        } catch DecodingError.dataCorrupted(_) {
            fatalError("Failed to decode \(file) from bundle because it appears to be invalid JSON")
        } catch {
            fatalError("Failed to decode \(file) from bundle: \(error.localizedDescription)")
        }
    }
}


struct GroceryProduct: Codable {
    var name: String
}

// Try running this and it won't work
let results = Bundle.main.decode(GroceryProduct.self, from: "test.json")


print(results.name)

You need to escape \ characters first - this can be done before decoding:您需要先转义\字符 - 这可以解码之前完成:

guard let data = try? Data(contentsOf: url) else {
    fatalError("Failed to load \(file) from bundle.")
}

let escaped = Data(String(data: data, encoding: .utf8)!.replacingOccurrences(of: "\0", with: "").utf8)
...
return try decoder.decode(T.self, from: escaped)

Note: force-unwrapping for simplicity only.注意:强制展开只是为了简单起见。


In Playground you can escape it with an additional \\ (to make it work):在 Playground 中,您可以使用额外的\\将其转义(使其工作):

let json = """
{
    "name": "Durian \\u0000"
}
""".data(using: .utf8)!

or replace it with \\0 (to make it fail - behave like during the decoding):或用\\0替换它(使其失败 - 在解码期间表现得像):

let json = """
{
    "name": "Durian \0"
}
""".data(using: .utf8)!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM