【问题标题】:JSONEncoder with multiple structures具有多种结构的 JSONEncoder
【发布时间】:2017-12-21 18:57:01
【问题描述】:

您好,我有多个 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)

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

【问题讨论】:

  • 你必须使用两个不同的结构或者你必须编写一个自定义的初始化器来区分情况

标签: json swift struct swift4 jsonencoder


【解决方案1】:

我有两个主要模型对象的结构,Location 和 Synchronization。然后我将它们定义为符合某些协议,在该协议中我们指定了我们如何知道哪个“标头”用于哪种类型的有效负载。然后我会制作一个通用的 Packet 来打包这两种可能的有效载荷:

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"
}

【讨论】:

    【解决方案2】:

    我建议你创建 3 个结构。

    1. 主要有数据结构和标头结构。

    每个结构都必须符合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))
    

    填写免费提问 eny 问题。下次在你问任何问题之前,试着用谷歌搜索一下。有很多很好的教程可以解决这类问题。

    Raywanderlich tutorial

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多