具有多个结构的JSONEncoder

时间:2017-12-21 18:57:01

标签: json swift struct swift4 jsonencoder

您好我有多个JSON数据包,就像我在下面写的那样。

{
  "data" : {
    "lng" : 36.159999999999997,
    "lat" : 50.359999999999999,
    "accuracy" : 5
  },
  "header" : {
    "type" : "loc"
  }
}

和这一个

{
  "data" : {
    "time" : 15646565455,
    "tz" : "+2",
    "system" : 5
  },
  "header" : {
    "type" : "syn"
  }
}

我有我的数据包的结构,它适用于一个数据包结构。但是如何将它用于多个数据包结构。

struct Packet : Codable {
    enum StructureType : String, Codable {
        case location = "loc"
        case synchronize = "syn"
    }

    enum Status: String, Codable {
        case  OK   = "OK"
        case  NOT   = "NOT"
    }

    struct Header: Codable {
        let type: StructureType
        let status: Status?
    }
    var header: Header

    struct Data : Codable {

        struct LocationStruct : Codable {
            var lng: Double
            var lat: Double
            var accuracy: Double
        }
        struct SynchronizationStruct: Codable {
            var time: Int
            var tz: String
            var locale: String
        }
    }
    var data: Data

}

现在我想编码JSON取决于我的数据

let dataHeader = Packet.Header.init(type: .location, action: nil, ID: nil, dataID: nil, status: nil)
        let dataData = Packet.Data.LocationStruct.init(lng: lng, lat: lat, accuracy: acc)
        let dataObject = Packet.init(header: dataHeader, data: dataData)

        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        let data = try! encoder.encode(dataObject)

如何做到这一点,或者我需要为每个数据包使用我的数据结构的其他结构?

2 个答案:

答案 0 :(得分:4)

我有两个主要模型对象LocationSynchronization的结构。然后我定义它们以符合某些协议,我们指定了如何知道哪个"标题"适用于哪种类型的有效载荷。然后我制作一个通用数据包,可以打包这两个可能的有效载荷:

enum PayloadType: String, Codable {
    case location = "loc"
    case synchronize = "syn"
}

protocol Payload: Codable {
    var payloadType: PayloadType { get }
}

struct Location: Payload {
    let lat: Double
    let long: Double
    let accuracy: Double
    let payloadType = PayloadType.location

    enum CodingKeys: String, CodingKey {
        case lat,long,accuracy
    }
}

struct Synchronization: Payload {
    let time: Int
    let tz: String
    let system: Int
    let payloadType = PayloadType.synchronize

    enum CodingKeys: String, CodingKey {
        case time, tz, system
    }
}

struct Packet<T: Payload>: Codable {
    let data: T
    let header: PayloadType

    init(payload: T) {
        data = payload
        header = payload.payloadType
    }
}

然后你可以这样做:

let location = Location(lat: 36.16, long: 50.36, accuracy: 5)
let packet = Packet(payload: location)

let json = try! encoder.encode(packet)

导致:

{
  "data" : {
    "lat" : 36.159999999999997,
    "long" : 50.359999999999999,
    "accuracy" : 5
  },
  "header" : "loc"
}

let location = Synchronization(time: 15646565455, tz: "+2", system: 5)
let packet = Packet(payload: location)

let json = try! encoder.encode(packet)

导致:

{
  "data" : {
    "system" : 5,
    "time" : 15646565455,
    "tz" : "+2"
  },
  "header" : "syn"
}

答案 1 :(得分:1)

我建议你创建3个结构。

  1. 主要有数据结构和标题结构。
  2. 每个结构必须符合Codable协议。

    struct Structure: Codable {
        let data: Data
        let header: Header
    
        init(data: Data, header: Header) {
            self.data = data
            self.header = header
        }
    
        enum CodingKeys: String, CodingKey { case data, header }
    
        public func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encodeIfPresent(data, forKey: .data)
            try container.encodeIfPresent(header, forKey: .header)
        }
    
    }
    
    
    struct Data: Codable {
        let lng: Double?
        let lat: Double?
        let accuracy: Double?
        let time: Int?
        let tz: String?
        let system: Int?
    }
    
    struct Header: Codable {
        let type: String
    }
    
    let firstStructure = Structure(data: Data(lng: 36.159999999999997, lat: 50.359999999999999, accuracy: 5, time: nil, tz: nil, system: nil), header: Header(type: "loc"))
    
    let secondStructure = Structure(data: Data(lng: nil, lat: nil, accuracy: nil, time: 15646565455, tz: "+2", system: 5), header: Header(type: "syn"))
    
    let encoder = JSONEncoder()
    
    let firstData = try? encoder.encode(firstStructure)
    let secondData = try? encoder.encode(secondStructure)
    
    print(String(data: firstData!, encoding: String.Encoding.ascii))
    print(String(data: secondData!, encoding: String.Encoding.ascii))
    

    enter image description here

    随意询问eny问题。下次在您提出任何问题之前,请尝试谷歌。有很多很好的教程可以解决这类问题。

    Raywanderlich tutorial