ios 怎么去掉字典json的null
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ios 怎么去掉字典json的null相关的知识,希望对你有一定的参考价值。
参考技术A 通过[x isKindOfClass:[NSNull class]]判断就可以了如果是null就改成@""- (NSArray *)checkNSArrayWithChangeUseful:(NSArray *)checkArray
if([checkArray isKindOfClass:[NSArray class]])
NSMutableArray *usefulArr = [NSMutableArray arrayWithArray:checkArray];
[usefulArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
if([obj isKindOfClass:[NSNull class]] )
[usefulArr replaceObjectAtIndex:idx withObject:@""];
else if([obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSValue class]])
[usefulArr replaceObjectAtIndex:idx withObject:[NSString stringWithFormat:@"%@",obj]];
else if([obj isKindOfClass:[NSDictionary class]])
[usefulArr replaceObjectAtIndex:idx withObject:[self checkNSDictinaryWithChangeUseful:obj]];
else if([obj isKindOfClass:[NSArray class]])
[usefulArr replaceObjectAtIndex:idx withObject:[self checkNSArrayWithChangeUseful:obj]];
];
return [NSArray arrayWithArray:usefulArr];
return checkArray;
- (NSDictionary *)checkNSDictinaryWithChangeUseful:(NSDictionary *)checkDictioary
if([checkDictioary isKindOfClass:[NSDictionary class]])
NSMutableDictionary *usefulDic = [NSMutableDictionary dictionaryWithDictionary:checkDictioary];
[usefulDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop)
if(ISNULL(obj) || ISNil(obj))
usefulDic[key] = @"";
else if([obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSValue class]])
usefulDic[key] = [NSString stringWithFormat:@"%@",obj];
else if([obj isKindOfClass:[NSDictionary class]])
usefulDic[key] = [self checkNSDictinaryWithChangeUseful: obj];
else if([obj isKindOfClass:[NSArray class]])
usefulDic[key] = [self checkNSArrayWithChangeUseful:obj];
];
return [NSDictionary dictionaryWithDictionary:usefulDic];
return checkDictioary;
在字典中解码字典 - JSON/Swift
【中文标题】在字典中解码字典 - JSON/Swift【英文标题】:Decoding a Dictionary Inside a Dictionary - JSON/Swift 【发布时间】:2020-09-25 00:23:59 【问题描述】:我有一个结构如下的 JSON 文件:
"forecast": [
"altimeter": "",
"clouds": [
"repr": "OVC025",
"type": "OVC",
"altitude": 25,
"modifier": null,
"direction": null
],
"flight_rules": "MVFR",
"other": [],
"sanitized": "0318/0424 34017G26KT P6SM -RA OVC025",
"visibility":
"repr": "P6",
"value": null,
"spoken": "greater than six"
,
"wind_direction":
"repr": "340",
"value": 340,
"spoken": "three four zero"
And so on....
我正在尝试使用 DispatchQueue 访问信息并更新 UI,但无法弄清楚如何从内部预测中提取数据:clouds: repr(或任何其他类似的嵌套)。我可以成功提取数据,例如:预测:原始。我尝试使用未嵌套在第一个中的结构,但它不起作用(正如预期的那样,数据是内部的另一个索引)。
我的解码文件是:
//
// TAFData.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/24/20.
//
import Foundation
struct TAFDatas: Codable
let flight_rules: String?
let time: TimeTAF?
let station: String?
let raw: String?
let forecast: [ForecastTAF?]
let end_time: ?
let wind_gust: ?
struct ForecastTAF: Codable
let raw: String?
struct CloudsTAF: Codable
let type: String
let altitude: Int
struct endTimeTAF: Codable
let repr: String
struct WindSpeedTAF: Codable
let value: Int
struct WindGustTAF: Codable
let value: Int
struct WindDirectionTAF: Codable
let repr: String
struct VisibilityTAF: Codable
let repr: String
struct WxcodesTAF: Codable
let value: String
struct StartTimeTAF: Codable
let repr: String
struct EndTimeTAF: Codable
let repr: String
struct TimeTAF: Codable
let repr: String
我的解析文件是:
//
// TAFManager.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/24/20.
//
import Foundation
protocol TAFManagerDelegate : class
func didUpdateTAF(_ weatherManager: TAFManager, weatherTAF: TAFModel)
func didFailWithErrorTAF(error: Error)
struct TAFManager
let TAFURL = "https://avwx.rest/api/taf/"
weak var delegate : TAFManagerDelegate?
func fetchWeatherTAF (stationICAO: String)
let TAFurlString = "\(TAFURL)\(stationICAO)?token=OVi45FiTDo1LmyodShfOfoizNe5m9wyuO6Mkc95AN-c"
performRequestTAF(with: TAFurlString)
func performRequestTAF (with TAFurlString: String)
if let TAFurl = URL(string: TAFurlString)
let session = URLSession(configuration: .default)
let taskTAF = session.dataTask(with: TAFurl) (data, response, error) in
if error != nil
self.delegate?.didFailWithErrorTAF(error: error!)
return
if let safeDataTAF = data
if let weatherTAF = self.parseJSONTAF(safeDataTAF)
self.delegate?.didUpdateTAF(self, weatherTAF: weatherTAF)
taskTAF.resume()
print(TAFurlString)
func parseJSONTAF(_ TAFData: Data) -> TAFModel?
do
let decoderTAF = JSONDecoder()
let decodedDataTAF = try decoderTAF.decode(TAFDatas.self, from: TAFData)
let cloudsTAF = decodedDataTAF.clouds
let wxcodesTAF = decodedDataTAF.wx_codes
let forecastTAF = decodedDataTAF.forecast
let lowCloudsTypeTAF = (cloudsTAF.count > 0 ? cloudsTAF[0]?.type : nil) ?? "N/A"
let midCloudsTypeTAF = (cloudsTAF.count > 1 ? cloudsTAF[1]?.type : nil) ?? "N/A"
let highCloudsTypeTAF = (cloudsTAF.count > 2 ? cloudsTAF[2]?.type : nil) ?? "N/A"
let lowCloudsAltTAF = (cloudsTAF.count > 0 ? cloudsTAF[0]?.altitude : nil) ?? 0
let midCloudsAltTAF = (cloudsTAF.count > 1 ? cloudsTAF[1]?.altitude : nil) ?? 0
let highCloudsAltTAF = (cloudsTAF.count > 2 ? cloudsTAF[2]?.altitude : nil) ?? 0
let reportingStationVarTAF = decodedDataTAF.station ?? "N/A"
let windGustValueTAF = decodedDataTAF.wind_gust?.value ?? 0
let windSpeedValueTAF = decodedDataTAF.wind_speed?.value ?? 0
let windDirectionValueTAF = decodedDataTAF.wind_direction?.repr ?? "N/A"
let visibilityValueTAF = decodedDataTAF.visibility?.repr ?? "N/A"
let flightRulesValueTAF = decodedDataTAF.flight_rules ?? "N/A"
let timeReportedTAF = decodedDataTAF.time?.repr ?? "N/A"
let firstWxCode1TAF = (wxcodesTAF.count > 0 ? wxcodesTAF[0]?.value : "N/A") ?? "N/A"
let startTimeTaf = decodedDataTAF.start_time?.repr ?? "N/A"
let endTimeTaf = (forecastTAF.count > 0 ? forecastTAF[0]? : nil) ?? "N/A"
let rawTAFData = (forecastTAF.count > 0 ? forecastTAF[0]?.raw : nil) ?? "N/A"
let weatherTAF = TAFModel(lowestCloudsTypeTAF: lowCloudsTypeTAF , lowestCloudsAltTAF: lowCloudsAltTAF, middleCloudsTypeTAF: midCloudsTypeTAF , middleCloudsAltTAF: midCloudsAltTAF, highestCloudsTypeTAF: highCloudsTypeTAF , highestCloudsAltTAF: highCloudsAltTAF, reportingStationTAF: reportingStationVarTAF, windGustTAF: windGustValueTAF, windSpeedTAF: windSpeedValueTAF, windDirectionTAF: windDirectionValueTAF, visibilityTAF: visibilityValueTAF, flightRulesTAF: flightRulesValueTAF, timeTAF: timeReportedTAF, startTimeTAF: startTimeTaf, endTimeTAF: endTimeTaf, firstWxCodeTAF: firstWxCode1TAF, rawTAF: rawTAFData)
delegate?.didUpdateTAF(self, weatherTAF: weatherTAF)
return weatherTAF
catch
delegate?.didFailWithErrorTAF(error: error)
return nil
我的模型文件是:
//
// WeatherModel.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/22/20.
//
import Foundation
struct WeatherModel
let lowestCloudsType: String
let lowestCloudsAlt: Int
let middleCloudsType: String
let middleCloudsAlt: Int
let highestCloudsType: String
let highestCloudsAlt: Int
let reportingStation: String
let windGust: Int
let windSpeed: Int
let windDirection: String
let visibility: String
let flightRules: String
let time: String
let remarks: String
let altimeter: Double
let temperature: String
let dewpoint: String
let firstWxCode: String
var altToString1: String
return String(format: "%u" + "00 ft", lowestCloudsAlt)
var altToString2: String
return String(format: "%u" + "00 ft", middleCloudsAlt)
var altToString3: String
return String(format: "%u" + "00 ft", highestCloudsAlt)
var windGustString: String
return String(format: "%u" + "kt", windGust)
var windSpeedString: String
return String(format: "%u" + "kt", windSpeed)
var altimeterString: String
return String(format: "%.2f" + " inHg", altimeter as CVarArg)
var visUnits: String
return visibility + " SM"
var degUnits: String
return windDirection + "°"
var tempUnits: String
return temperature + "°C"
var dewUnits: String
return dewpoint + "°C"
var flightConditions: String
switch flightRules
case "VFR":
return "green"
case "MVFR":
return "blue"
case "IFR":
return "red"
case "LIFR":
return "purple"
default:
return "gray"
我认为主要的问题是获取这些数据键。一旦我在那里,希望其余的都会到位。非常感谢提前提供的帮助,祝您有美好的一天!
加上评论,我的新 JSON
// MARK: - TAFData
struct TAFData: Codable
let meta: MetaTAF?
let raw, station: String?
let time: TimeTAF?
let remarks: String?
let forecast: [ForecastTAF?]
let startTime, endTime: TimeTAF?
let maxTemp, minTemp: String?
let alts, temps: JSONNull?
enum CodingKeys: String, CodingKey
case meta, raw, station, time, remarks, forecast
case startTime = "start_time"
case endTime = "end_time"
case maxTemp = "max_temp"
case minTemp = "min_temp"
case alts, temps, units
// MARK: - Time
struct TimeTAF: Codable
let repr, dt: String
// MARK: - Forecast
struct ForecastTAF: Codable
let altimeter: String
let clouds: [CloudTAF]
let flightRules: String
let other: [JSONAny]
let sanitized: String
let visibility, windDirection: VisibilityTAF
let windGust: VisibilityTAF?
let windSpeed: VisibilityTAF
let wxCodes: [WxCodeTAF]
let endTime: TimeTAF
let icing: [JSONAny]
let probability: JSONNull?
let raw: String
let startTime: TimeTAF
let turbulence: [JSONAny]
let type: String
let windShear: JSONNull?
let summary: String
enum CodingKeys: String, CodingKey
case altimeter, clouds
case flightRules = "flight_rules"
case other, sanitized, visibility
case windDirection = "wind_direction"
case windGust = "wind_gust"
case windSpeed = "wind_speed"
case wxCodes = "wx_codes"
case endTime = "end_time"
case icing, probability, raw
case startTime = "start_time"
case turbulence, type
case windShear = "wind_shear"
case summary
// MARK: - Cloud
struct CloudTAF: Codable
let repr, type: String
let altitude: Int
let modifier, direction: JSONNull?
// MARK: - Visibility
struct VisibilityTAF: Codable
let repr: String
let value: Int?
let spoken: String
// MARK: - WxCode
struct WxCodeTAF: Codable
let repr, value: String
// MARK: - Meta
struct MetaTAF: Codable
let timestamp: String
// MARK: - Units
struct UnitsTAF: Codable
let altimeter, altitude, temperature, visibility: String
let windSpeed: String
enum CodingKeys: String, CodingKey
case altimeter, altitude, temperature, visibility
case windSpeed = "wind_speed"
// MARK: - Encode/decode helpers
class JSONNull: Codable, Hashable
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool
return true
public var hashValue: Int
return 0
public func hash(into hasher: inout Hasher)
// No-op
public init()
public required init(from decoder: Decoder) throws
let container = try decoder.singleValueContainer()
if !container.decodeNil()
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
public func encode(to encoder: Encoder) throws
var container = encoder.singleValueContainer()
try container.encodeNil()
class JSONCodingKey: CodingKey
let key: String
required init?(intValue: Int)
return nil
required init?(stringValue: String)
key = stringValue
var intValue: Int?
return nil
var stringValue: String
return key
class JSONAny: Codable
let value: Any
static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError
let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny")
return DecodingError.typeMismatch(JSONAny.self, context)
static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError
let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny")
return EncodingError.invalidValue(value, context)
static func decode(from container: SingleValueDecodingContainer) throws -> Any
if let value = try? container.decode(Bool.self)
return value
if let value = try? container.decode(Int64.self)
return value
if let value = try? container.decode(Double.self)
return value
if let value = try? container.decode(String.self)
return value
if container.decodeNil()
return JSONNull()
throw decodingError(forCodingPath: container.codingPath)
static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any
if let value = try? container.decode(Bool.self)
return value
if let value = try? container.decode(Int64.self)
return value
if let value = try? container.decode(Double.self)
return value
if let value = try? container.decode(String.self)
return value
if let value = try? container.decodeNil()
if value
return JSONNull()
if var container = try? container.nestedUnkeyedContainer()
return try decodeArray(from: &container)
if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self)
return try decodeDictionary(from: &container)
throw decodingError(forCodingPath: container.codingPath)
static func decode(from container: inout KeyedDecodingContainer<JSONCodingKey>, forKey key: JSONCodingKey) throws -> Any
if let value = try? container.decode(Bool.self, forKey: key)
return value
if let value = try? container.decode(Int64.self, forKey: key)
return value
if let value = try? container.decode(Double.self, forKey: key)
return value
if let value = try? container.decode(String.self, forKey: key)
return value
if let value = try? container.decodeNil(forKey: key)
if value
return JSONNull()
if var container = try? container.nestedUnkeyedContainer(forKey: key)
return try decodeArray(from: &container)
if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key)
return try decodeDictionary(from: &container)
throw decodingError(forCodingPath: container.codingPath)
static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any]
var arr: [Any] = []
while !container.isAtEnd
let value = try decode(from: &container)
arr.append(value)
return arr
static func decodeDictionary(from container: inout KeyedDecodingContainer<JSONCodingKey>) throws -> [String: Any]
var dict = [String: Any]()
for key in container.allKeys
let value = try decode(from: &container, forKey: key)
dict[key.stringValue] = value
return dict
static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws
for value in array
if let value = value as? Bool
try container.encode(value)
else if let value = value as? Int64
try container.encode(value)
else if let value = value as? Double
try container.encode(value)
else if let value = value as? String
try container.encode(value)
else if value is JSONNull
try container.encodeNil()
else if let value = value as? [Any]
var container = container.nestedUnkeyedContainer()
try encode(to: &container, array: value)
else if let value = value as? [String: Any]
var container = container.nestedContainer(keyedBy: JSONCodingKey.self)
try encode(to: &container, dictionary: value)
else
throw encodingError(forValue: value, codingPath: container.codingPath)
static func encode(to container: inout KeyedEncodingContainer<JSONCodingKey>, dictionary: [String: Any]) throws
for (key, value) in dictionary
let key = JSONCodingKey(stringValue: key)!
if let value = value as? Bool
try container.encode(value, forKey: key)
else if let value = value as? Int64
try container.encode(value, forKey: key)
else if let value = value as? Double
try container.encode(value, forKey: key)
else if let value = value as? String
try container.encode(value, forKey: key)
else if value is JSONNull
try container.encodeNil(forKey: key)
else if let value = value as? [Any]
var container = container.nestedUnkeyedContainer(forKey: key)
try encode(to: &container, array: value)
else if let value = value as? [String: Any]
var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key)
try encode(to: &container, dictionary: value)
else
throw encodingError(forValue: value, codingPath: container.codingPath)
static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws
if let value = value as? Bool
try container.encode(value)
else if let value = value as? Int64
try container.encode(value)
else if let value = value as? Double
try container.encode(value)
else if let value = value as? String
try container.encode(value)
else if value is JSONNull
try container.encodeNil()
else
throw encodingError(forValue: value, codingPath: container.codingPath)
public required init(from decoder: Decoder) throws
if var arrayContainer = try? decoder.unkeyedContainer()
self.value = try JSONAny.decodeArray(from: &arrayContainer)
else if var container = try? decoder.container(keyedBy: JSONCodingKey.self)
self.value = try JSONAny.decodeDictionary(from: &container)
else
let container = try decoder.singleValueContainer()
self.value = try JSONAny.decode(from: container)
public func encode(to encoder: Encoder) throws
if let arr = self.value as? [Any]
var container = encoder.unkeyedContainer()
try JSONAny.encode(to: &container, array: arr)
else if let dict = self.value as? [String: Any]
var container = encoder.container(keyedBy: JSONCodingKey.self)
try JSONAny.encode(to: &container, dictionary: dict)
else
var container = encoder.singleValueContainer()
try JSONAny.encode(to: &container, value: self.value)
【问题讨论】:
【参考方案1】:我可能会使用不同的模型,因为您当前的模型不支持与 JSON 相同的格式:
struct Forecast: Codable
let altimeter: String
let clouds: [Cloud]
let flightRules: String
let other: [JSONAny]
let sanitized: String
let visibility, windDirection: Visibility
enum CodingKeys: String, CodingKey
case altimeter, clouds
case flightRules = "flight_rules"
case other, sanitized, visibility
case windDirection = "wind_direction"
// MARK: - Cloud
struct Cloud: Codable
let repr, type: String
let altitude: Int
// MARK: - Visibility
struct Visibility: Codable
let repr: String
let value: Int?
let spoken: String
这样你就可以使用了:
if let cloud = forecast.clouds.first()
let repr = cloud.repr
.. Your logic
我的模型中可能缺少一些东西,但你应该知道
【讨论】:
我正在轮询的数据有多个预测部分——即预测:[forecast1 with all that data、forecast two with all that data等]。该逻辑是否允许我创建所有数据的多个实例?感谢您的回答,我正在努力尝试! 这些是我的 JSON 数据:avwx.docs.apiary.io/#reference/0/parse-metar/get-taf-report 这仅适用于您在问题中发送的 JSON,如果您有很多多个来源,您可以使用此工具帮助您对所有内容进行建模:app.quicktype.io 这是一个很棒的工具。感谢分享!我将新的 JSON 放在我的问题帖子的底部。在 TAFManager 上,我如何访问预测 > 云 > 类型中的内容? 我试过了:给定let forecastTAF = decodedDataTAF.forecast
forecastTAF.CloudsTAF[0].type
、forecastTAF.clouds[0].type
和其他一些。以上是关于ios 怎么去掉字典json的null的主要内容,如果未能解决你的问题,请参考以下文章
alibaba的JSON.toString会把值为null的字段去掉,谨记
iOS NSDictionary 转Json 去掉换行去掉空格