【问题标题】:Is this poorly formed JSON?这是格式不正确的 JSON 吗?
【发布时间】:2020-11-29 17:24:49
【问题描述】:

我正在学习一个使用 Whitehouse 请愿 JSON 提要的在线教程。我正在使用 Swift 5 并且已经实现了我的结构以符合 Codable。 Whitehouse JSON 导致 Codable 错误。下面是 JSON 的 sn-p。引起麻烦的部分是“响应”。在第一个示例中,我希望它是一个空数组,但是当它具有第二个示例中的值时,JSON 从 [] 切换到 {},如下所示。

[ ] 示例:

  "results":[
      {
         "id":"2722358",
         "type":"petition",
         "title":"Remove Chuck Schumer and Nancy Pelosi from office",
         "body":"Schumer and Pelosi's hatred and refusing to work with...",
         "petition_type":[
          {
              "id":291,
              "name":"Call on Congress to act on an issue"
          }
        ],
        "signatureThreshold":100000,
        "status":"closed",
        "response":[

        ],
        "created":1547050064,
        "isSignable":false,
        "isPublic":true,
        "reachedPublic":0
       },

{ } 示例

  "results":[
  {
     "id":"2722358",
     "type":"petition",
     "title":"Remove Chuck Schumer and Nancy Pelosi from office",
     "body":"Schumer and Pelosi's hatred and refusing to work with...",
     "petition_type":[
      {
          "id":291,
          "name":"Call on Congress to act on an issue"
      }
    ],
    "signatureThreshold":100000,
    "status":"closed",
    "response":{
         "id":2630367,
         "url":"https://petitions.whitehouse.gov/response/response-your-petition-3",
    },
    "created":1547050064,
    "isSignable":false,
    "isPublic":true,
    "reachedPublic":0
   },

从我对该问题的研究中可以看出,JSON 的编写应该一致。换句话说,由于“响应”从来都不是一个数组,而只是一个单一的值,所以当它为空时应该写为 { } 而不是 [ ] 。我对此的理解正确吗?

【问题讨论】:

  • 嗯。它称它为有效。即使其中一个显示为 [ ] 和一个显示为 { },其中包含内容。 Codable 抛出一个错误,基本上说是预期的数组。
  • 谢谢@dratenik。为了便于阅读,我把正文删掉了,忘记加引号了。
  • 而且,我一如既往地感谢投反对票...不知道为什么我回到这个网站。
  • 不确定这是否有帮助? stackoverflow.com/questions/52681385/…
  • 这是另一篇文章:medium.com/@sajjadsarkoobi/…

标签: json swift5 codable


【解决方案1】:

如果您仅在response 属性没有值时获得空数组,则可以将response 属性设为可选,然后执行解码并捕获DecodingError.typeMismatch 错误,如下所示:

struct Results: Decodable {
    let results: [Result]
}

struct Result: Decodable {
    let id: String
    let type: String
    let title: String
    let body: String
    let petition_type: [PetitionType]
    let signatureThreshold: Int
    let status: String
    let response: Response?
    let created: Date
    let isSignable: Bool
    let isPublic: Bool
    let reachedPublic: Int
    
    enum CodingKeys: String, CodingKey {
        case id
        case type
        case title
        case body
        case petition_type
        case signatureThreshold
        case status
        case response
        case created
        case isSignable
        case isPublic
        case reachedPublic
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        id = try container.decode(String.self, forKey: .id)
        type = try container.decode(String.self, forKey: .type)
        title = try container.decode(String.self, forKey: .title)
        body = try container.decode(String.self, forKey: .body)
        petition_type = try container.decode([PetitionType].self, forKey: .petition_type)
        signatureThreshold = try container.decode(Int.self, forKey: .signatureThreshold)
        status = try container.decode(String.self, forKey: .status)
        
        do {
            response = try container.decode(Response.self, forKey: .response)
        } catch DecodingError.typeMismatch {
            response = nil
        }
        
        created = try container.decode(Date.self, forKey: .created)
        isSignable = try container.decode(Bool.self, forKey: .isSignable)
        isPublic = try container.decode(Bool.self, forKey: .isPublic)
        reachedPublic = try container.decode(Int.self, forKey: .reachedPublic)
    }
}

struct PetitionType: Decodable {
    var id: Int
    var name: String
}

struct Response: Decodable {
    let id: Int
    let url: String
}

【讨论】:

    【解决方案2】:

    就我个人而言,我只会创建一个解码包装器:

    struct InvalidDecodableWrapper<T: Decodable>: Decodable {
        let value: T?
    
        init(from decoder: Decoder) throws {
            guard let container = try? decoder.singleValueContainer() else {
                value = nil
                return
            }
    
            value = try container.decode(T.self)
        }
    }
    
    struct Response: Decodable {
        let id: Int
        let url: String
    }
    
    struct Result: Decodable {    
        ...
        let response: InvalidDecodableWrapper<Response>
        ...
    }
    

    【讨论】:

      【解决方案3】:

      感谢所有回复。我找到了适合我的解决方案 here.

      我创建了一个新结构:

      struct Response: Codable {
          var id: Int
          var url: String
      }
      

      然后创建了我的 Petition 结构的扩展:

      struct Petition {
          var title: String
          var body: String
          var signatureCount: Int
          var signatureThreshold: Int
          var signaturesNeeded: Int
          var status: String
          var response: [Response]
          var issues: Array<Issue>
       }
      
      extension Petition: Codable {
          public init(from decoder: Decoder) throws {
              let container = try decoder.container(keyedBy: CodingKeys.self)
              title = try container.decode(String.self, forKey: .title)
              body  = try container.decode(String.self, forKey: .body)
              signatureCount = try container.decode(Int.self, forKey: .signatureCount)
              signatureThreshold = try container.decode(Int.self, forKey: .signatureThreshold)
              signaturesNeeded = try container.decode(Int.self, forKey: .signaturesNeeded)
              status = try container.decode(String.self, forKey: .status)
              do {
                  response = try [container.decode(Response.self, forKey: .response)]
              } catch {
                  response = try container.decode([Response].self, forKey: .response)
              }
              issues = try container.decode([Issue].self, forKey: .issues)
          }
      }
      

      结果是我最终得到一个空数组,或者一个具有单个 Response 结构的数组,我能够正确访问。因此,在我的 viewController 中,我只需检查 response.count > 0 是否是安全的,如果是,则可以安全地访问 response[0].url 等...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-04
        • 2015-09-02
        • 2015-08-29
        • 2011-12-18
        • 1970-01-01
        • 2021-02-01
        相关资源
        最近更新 更多