Swift JSONDecoder - 编码密钥不使用下划线

问题描述 投票:0回答:2

有人可以解释为什么A部分的代码有效,B不满意。让我感到困惑。

工作

struct Coded : Codable, Hashable {  
  public let avar1: String
  public let avar2: String

  enum CodingKeys: String, CodingKey {
    case avar1 = "avar1"
    case avar2 = "avar2"
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    print (container.allKeys)
    avar1 = try container.decode(String.self, forKey: .avar1)
    avar2 = try container.decode(String.self, forKey: .avar2)
  }
}

let JSONStr = """
{
  "avar1": "This is a string",
  "avar2": "This is a string2",
}
"""

if let jsdata = JSONStr.data(using: .utf8) {
  let decoder = JSONDecoder()
  decoder.keyDecodingStrategy = .convertFromSnakeCase
  let aobj: Coded? = try? decoder.decode(Coded.self, from: jsdata)
  print (aobj ?? "No object")
}

OUTPUT

[CodingKeys(stringValue: "avar1", intValue: nil), CodingKeys(stringValue: "avar2", intValue: nil)]
Coded(avar1: "This is a string", avar2: "This is a string2")

不工作

struct Coded : Codable, Hashable {  
  public let avar1: String
  public let avar2: String

  enum CodingKeys: String, CodingKey {
    case avar1 = "avar1"
    case avar2 = "avar_2"
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    print (container.allKeys)
    avar1 = try container.decode(String.self, forKey: .avar1)
    avar2 = try container.decode(String.self, forKey: .avar2)
  }
}

let JSONStr = """
{
  "avar1": "This is a string",
  "avar_2": "This is a string2",
}
"""

if let jsdata = JSONStr.data(using: .utf8) {
  let decoder = JSONDecoder()
  decoder.keyDecodingStrategy = .convertFromSnakeCase
  let aobj: Coded? = try? decoder.decode(Coded.self, from: jsdata)
  print (aobj ?? "No object")
}

OUTPUT

[CodingKeys(stringValue: "avar1", intValue: nil)]
No object

第二个函数只显示没有下划线的编码密钥。但是一旦我删除下划线,它就会在allKeys中拥有编码密钥......

Swift 4.2 - Xcode 10.2。

有任何想法吗?

ios json swift decoding codable
2个回答
1
投票

在访问.convertFromSnakeCase之前,CodingKeys将基于snake_cased的变量转换为camelCase。

如果要指定CodingKeys,则必须在NOT WORKING示例中使用转换后的值

enum CodingKeys: String, CodingKey {
    case avar1 = "avar1"
    case avar2 = "avar2"
}

但这说明了CodingKeys的无意义。因此,反过来考虑并利用关键解码策略。

而不是删除.convertFromSnakeCase删除CodingKeys和初始化程序。

并始终抓住Decoding错误。

struct Coded : Codable {
    public let avar1: String
    public let avar2: String
}

let jsonStr = """
{
"avar1": "This is a string",
"avar_2": "This is a string2",
}
"""

let jsdata = Data(jsonStr.utf8)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
    let aobj = try decoder.decode(Coded.self, from: jsdata)
    print(aobj)
} catch { print(error) }

0
投票

我已经解决了这个问题。它源于Snake Case出现的问题。在某些情况下可能会导致问题。他们是什么,为什么他们发生,我不确定。但是如果你有一个启用了Snake Case Startegy的JSONDecoder。它将删除使用snake case编码的项目的KeyCodings。

通过从我的JSONDecoder中删除以下内容,我能够解决问题。

请删除以下内容并将Coding Strings强制转换为snake case,如果您设置了此参数并使用.convertFromSnakeCase强制执行JSONDecoder策略,它将删除Coding Key字符串并在解码期间中断。

如果您的编码密钥包括

codingKey = "a_json_var"

如果添加convertFromSnakeCase,这将完全删除编码密钥。所以,不要在你的编码密钥案例中指定一个文本字符串,否则它会破坏。

删除 - >

decoder.keyDecodingStrategy = .convertFromSnakeCase

如果要正确指定确切的编码键文本名称。

© www.soinside.com 2019 - 2024. All rights reserved.