【问题标题】:Dictionary Key Order in Swift 4 JSONEncoderSwift 4 JSONEncoder 中的字典键顺序
【发布时间】:2018-06-01 09:58:50
【问题描述】:

是否可以将 Swift JSON 编码器配置为使用结构属性的排序顺序作为 JSON 输出中字典键的排序顺序?默认情况下,它使用一些任意(但看似非随机)的顺序,例如...

struct Example: Codable {
  let id: Int
  let name: String
  let createdAt: Date
  let comments: [String]
}

...结果...

"example" : {
  "id" : 1,
  "name" : "Test",
  "comments" : [
    "Comment 1",
    "Comment 2"
  ],
  "createdAt" : 549539643.25327206
}

我知道在语义上顺序无关紧要,但我想保留它以用于调试目的。

【问题讨论】:

  • 不按结构属性的顺序,但let encoder = JSONEncoder(); encoder.outputFormatting = .sortedKeys 可能就足够了。
  • @vadian 你的评论和我的回答之间只有几分之一秒的差异:)
  • 是的,我知道那个设置,但我真的很想保留结构顺序,例如将“id”作为第一个属性。
  • 短篇小说:合成编码器无法做到这一点。
  • @vadian 是对的

标签: json swift codable


【解决方案1】:

JSONEncoderoutputFormatting 属性,你可以这样做,

let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys

我没试过,请尝试告诉我。

【讨论】:

  • 不幸的是,该设置使用字典/字母顺序。
  • .sortedKeys 也只能从 iOS 11 开始使用
  • 值得注意的是,您可以混合搭配不同的格式设置,例如swift encoder.outputFormatting = [.sortedKeys, .prettyPrinted]
【解决方案2】:

我想出的最好的(希望是临时的)解决方案是使用 CodingKeys 使用按字典顺序按正确顺序排列的前缀指定编码键,然后使用编辑器删除前缀。

例如,我的结构开始:

struct Creature : Codable 
    let name : String
    let size : SizeType
    let type : String
    var cr : String?
    var level : Int?
    let source : String?
    let page : Int?
    ...

然后我将 CodingKeys 枚举指定为:

    private enum CodingKeys : String, CodingKey {
    case name = "00name", size = "01size", type = "02type",
    cr = "03cr",level = "04level",
    source = "05source", page = "06source",
    templates, alignment, ac, hp, speeds,

并使用 .prettyprinted.sortedKeys JSONEncoder.OutputFormatting 选项生成此 JSON(示例):

{ "00name": "底栖鱼", "01size": "L", "02type": "像差", “03cr”:“10”, "05source": "MM", “06来源”:13, “能力”: [{ “名称”:“str”, “价值”:21 }, { “名称”:“dex”, “价值”:9 }, { “名称”:“骗局”, “价值”:15 }, { “名称”:“整数”, “价值”:18 }, { “名称”:“是”, “价值”:15 }, { “名称”:“茶”, “价值”:18 } ], “交流”:{ “交流”:17,

现在我可以使用编辑器轻松删除“00”、“01”等。是的,这是一个 hack,但实现了我现在想要的。我想人们也可以编写一个外部(或内部)JSON 重写器,并且会想象这样的存在吗?

【讨论】:

    【解决方案3】:

    目前无法实现,但有一个开放的请求 JSONEncoder should allow custom key ordering behavior

    我遇到了一个问题,我无法控制的服务要求字段按特定顺序排列 - 这是一个小请求,所以我最终预先格式化了 json 并使用插值插入值。

    【讨论】:

      【解决方案4】:

      问题是关于配置合成编码器...只是澄清通过实现encode(to encoder: Encoder)可以获得固定顺序:

      struct Example: Codable {
         let id: Int
         let name: String
         let createdAt: Date
         let comments: [String]
      }
      
      extension Example {
          enum CodingKeys: String, CodingKey {
              case id
              case name
              case createdAt
              case comments
          }
      
          func encode(to encoder: Encoder) throws {
              var container = encoder.container(keyedBy: CodingKeys.self)
              try container.encode(id, forKey: .id)
              try container.encode(name, forKey: .name)
              try container.encode(createdAt, forKey: .createdAt)
              try container.encode(comments, forKey: .comments)
          }
      }
      

      【讨论】:

      • 我在我的应用程序中使用 CodingKeyscontainer.encode,并且 JSON 没有按照我对值进行编码的顺序存储。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      相关资源
      最近更新 更多