Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使用动态类型序列化JSON_Ios_Json_Swift_Object_Serialization - Fatal编程技术网

Ios 如何使用动态类型序列化JSON

Ios 如何使用动态类型序列化JSON,ios,json,swift,object,serialization,Ios,Json,Swift,Object,Serialization,我需要序列化以下类型的JSON响应。哪个有不同的类型 [{ "type": "respiration_rate", "value": 45 } { "type": "blood_pressure", "value": { hg: 50 ,mm:120 } }] 我用于序列化上层json的类是 class Template: Codable { var type: String? var value: Double? private enum CodingKeys: St

我需要序列化以下类型的JSON响应。哪个有不同的类型

[{
 "type": "respiration_rate",
 "value": 45
}
{ "type": "blood_pressure",
 "value": { hg: 50 ,mm:120 }
}]
我用于序列化上层json的类是

class Template: Codable {
   var type: String?
   var value: Double?
   private enum CodingKeys: String, CodingKey {
        case type
        case value
    }
  }

如何序列化
它是双精度还是动态对象

以下是您需要的代码:

class Template: Codable {
    let type: String?
    let value: Value?

    private enum CodingKeys: String, CodingKey {
        case type
        case value
    }

    typealias ValueDictionary = Dictionary<String, Int>
    enum Value: Codable {
        case double(Double)
        case object(ValueDictionary)

        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let x = try? container.decode(Double.self) {
                self = .double(x)
                return
            }
            if let x = try? container.decode(ValueDictionary.self) {
                self = .object(x)
                return
            }
            throw DecodingError.typeMismatch(Value.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ValueUnion"))
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            switch self {
            case .double(let x):
                try container.encode(x)
            case .object(let x):
                try container.encode(x)
            }
        }
    }
}
类模板:可编码{
让类型:字符串?
让价值:价值?
私有枚举编码键:字符串,编码键{
案例类型
案例价值
}
typealias ValueDictionary=字典
枚举值:可编码{
双箱(双箱)
案例对象(ValueDictionary)
init(来自解码器:解码器)抛出{
let container=尝试解码器。singleValueContainer()
如果让x=try?container.decode(Double.self){
self=.double(x)
返回
}
如果让x=try?container.decode(ValueDictionary.self){
self=.object(x)
返回
}
抛出DecodingError.typeMismatch(Value.self,DecodingError.Context(codingPath:decoder.codingPath,debugDescription:“ValueUnion的类型错误”))
}
func encode(到编码器:编码器)抛出{
var container=encoder.singleValueContainer()
切换自身{
双格(x):
尝试容器编码(x)
case.object(设x):
尝试容器编码(x)
}
}
}
}

您可以使用带有关联值的枚举,而不是类,因为JSON格式似乎是异构的

enum Value: Decodable {
    case respirationRate(Double)
    case bloodPressure(hg: Double, mm: Double)

    private struct BloodPresure: Decodable {
        let hg: Double
        let mm: Double
    }

    private enum CodingKeys: String, CodingKey {
        case type
        case value
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        switch try container.decode(String.self, forKey: .type) {
        case "respiration_rate":
            self = try .respirationRate(container.decode(Double.self, forKey: .value))
        case "blood_pressure":
            let details = try container.decode(BloodPresure.self, forKey: .value)
            self = .bloodPressure(hg: details.hg, mm: details.mm)
        case let type: throw DecodingError.dataCorruptedError(forKey: .value, in: container, debugDescription: "Invalid type: \(type)")
        }
    }
}
解码json现在很容易:

let json = """
[{
"type": "respiration_rate",
"value": 45
},
{ "type": "blood_pressure",
"value": { "hg": 50 ,"mm":120 }
}]
"""

do {
    let values = try JSONDecoder().decode([Value].self, from: json.data(using: .utf8)!)
    print(values)
} catch {
    print(error)
}

使用
Any?
代替
Double?
并在稍后阶段转换为受尊重的类型(使用该值时)使用
Any?
抛出
不符合协议
编译时错误。我可能会建议您退回到手动解析,以便可以创建适当类型结构的实例。如果您只有这两个选项,
呼吸率
将有一个对象的值
血压
?试试看