【问题标题】:swift - convert json type Int to Stringswift - 将 json 类型 Int 转换为 String
【发布时间】:2018-03-06 17:17:15
【问题描述】:

我有如下代码这样的 json 数据:

{
"all": [
    {
        "ModelId": 1,
        "name": "ghe",
        "width": 2
    },
    {
        "ModelId": 2,
        "name": "ban",
        "width": 3
    }]
}

我尝试获取 modelId 并将其转换为字符串,但它不适用于我的代码:

let data = NSData(contentsOf: URL(string: url)!)
                do {
                    if let data = data, let json = try JSONSerialization.jsonObject(with: data as Data) as? [String: Any], let models = json["all"] as? [[String:Any]] {
                        for model in models {
                            if let name = model["ModelId"] as? String {
                                _modelList.append(name)
                            }
                        }
                    }
                    completion(_modelList)
                }catch {
                    print("error")
                    completion(nil)
                }

如何解决这个问题?谢谢。

【问题讨论】:

  • 是的,修复键名并创建一个字符串而不是强制转换。类似于:if let name = String(model["ModelId"])...,尽管您可能希望分两步完成,因为它将是一个可选的整数。
  • @EricS 它仍然无法正常工作...
  • @DucPhan ModelID 是整数而不是字符串
  • 请注意,您不应使用 NSData(contentsOf:URL) 同步获取非本地资源文件。您应该使用 URLSession dataTask(with: URL) 异步获取它。

标签: json swift


【解决方案1】:

我认为ModelId 是整数类型。那么,您可以尝试将其转换为整数吗

for model in models {
      if let name = model["ModelId"] as? Int{
           _modelList.append("\(name)")
       }
  }

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    if let as? 是展开,而不是类型转换。所以你先解包,然后你把它转换成字符串。

       for model in models {
          if let name = model["ModelId"] as? Int {
              _modelList.append("\(name)")
          }
       }
    

    【讨论】:

    • 什么意思???这是从AnyInt 的条件转换。顺便说一句,字符串插值不是演员表
    【解决方案3】:

    目前你正在寻找一个错误的钥匙,

     for model in models {
          if let name = model["ModelId"] as? NSNumber {
               _modelList.append(name.stringValue)
           }
      }
    

    【讨论】:

    • 这不起作用,因为模型 id 值是数字,而不是字符串。
    • 我很抱歉我帖子中的价格键是错误的,但是当我使用 ModelId 编辑键时它仍然无法正常工作...
    • @Sh_Khan OP json 的根对象是字典而不是数组
    • @Sh_Khan 确实是一本字典。 OP 可以投射整个 json as? [String: [[String: Any]]]
    • @LeoDabus ModelId 被认为是从所有 key 访问的数组的 0 索引中的一个项目,如果你查看 key 所有它在同一事物中,outer 是 { ,这意味着 json 是数组
    【解决方案4】:

    只要您使用JSONSerialization.jsonObject 解析您的 JSON,您几乎无法控制反序列化器将创建的类型,您基本上让解析器决定。明智的是,它将从不带引号的数字创建“某种”NSNumber Int 类型。这不能转换为String,因此您的程序将失败。

    您可以做不同的事情来“解决”这个问题,我想建议使用Codable 协议进行 JSON 解析,但这个特定问题可能只能使用看起来有点冗长的自定义初始化程序来解决如在this question 中所见。

    如果您只想转换您的NSNumber ModelIdString,您将不得不创建一个新对象(而不是徒劳地尝试转换)。在您的上下文中,这可能只是

    if let name = String(model["ModelId"]) { ...
    

    这仍然不是一个优雅的解决方案,但它会解决手头的问题。

    【讨论】:

      【解决方案5】:

      另一种方法是:

      import Foundation
      
      struct IntString: Codable
      {
          var value: String = "0"
          
          init(from decoder: Decoder) throws
          {
              // get this instance json value
              let container = try decoder.singleValueContainer()
              
              do
              {
                  // try to parse the value as int
                  value = try String(container.decode(Int.self))
              }
              catch
              {
                  // if we failed parsing the value as int, try to parse it as a string
                  value = try container.decode(String.self)
              }
          }
      
          func encode(to encoder: Encoder) throws
          {
            var container = encoder.singleValueContainer()
            try container.encode(value)
          }
      }
      

      我的解决方案是创建一个新结构,该结构将能够接收 String 或 Int 并将其解析为字符串,这样在我的代码中我可以决定如何处理它,以及当我的服务器有时向我发送一个 Int 值,有时是一个与 String 值具有相同键的 json - 解析器可以解析它而不会失败

      当然,您可以使用任何类型(日期/双精度/浮点/甚至完整结构)来执行此操作,甚至可以使用您自己的一些逻辑插入它(例如根据接收到的值获取枚举的字符串值并将其用作索引或其他)

      所以你的代码应该是这样的:

      import Foundation
      
      struct Models: Codable {
          let all: [All]
      }
      
      struct All: Codable {
          let modelID: IntString
          let name: String
          let width: IntString
      
          enum CodingKeys: String, CodingKey {
              case modelID = "ModelId"
              case name = "name"
              case width = "width"
          }
      }
      

      将 json 解析为 Models 结构体:

      let receivedModel: Decodable = Bundle.main.decode(Models.self, from: jsonData!)
      

      假设你的 json 解码器是:

      import Foundation
      
      extension Bundle
      {
          func decode<T: Decodable>(_ type: T.Type, from jsonData: Data, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> T
          {
      
              let decoder = JSONDecoder()
              decoder.dateDecodingStrategy = dateDecodingStrategy
              decoder.keyDecodingStrategy = keyDecodingStrategy
      
              do
              {
                  return try decoder.decode(T.self, from: jsonData)
              }
              catch DecodingError.keyNotFound(let key, let context)
              {
                  fatalError("Failed to decode \(jsonData) from bundle due to missing key '\(key.stringValue)' not found – \(context.debugDescription)")
              }
              catch DecodingError.typeMismatch(let type, let context)
              {
                  print("Failed to parse type: \(type) due to type mismatch – \(context.debugDescription) the received JSON: \(String(decoding: jsonData, as: UTF8.self))")
                  fatalError("Failed to decode \(jsonData) from bundle due to type mismatch – \(context.debugDescription)")
              }
              catch DecodingError.valueNotFound(let type, let context)
              {
                  fatalError("Failed to decode \(jsonData) from bundle due to missing \(type) value – \(context.debugDescription)")
              }
              catch DecodingError.dataCorrupted(_)
              {
                  fatalError("Failed to decode \(jsonData) from bundle because it appears to be invalid JSON")
              }
              catch
              {
                  fatalError("Failed to decode \(jsonData) from bundle: \(error.localizedDescription)")
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-20
        • 1970-01-01
        • 2014-08-01
        • 2014-07-29
        相关资源
        最近更新 更多