问题
Hi I have multiple JSON Packets like I wrote below.
{
"data" : {
"lng" : 36.159999999999997,
"lat" : 50.359999999999999,
"accuracy" : 5
},
"header" : {
"type" : "loc"
}
}
and this one
{
"data" : {
"time" : 15646565455,
"tz" : "+2",
"system" : 5
},
"header" : {
"type" : "syn"
}
}
I have structure for my packets and it worked for one structure of packets. But how to use it for multiple packets structures.
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
}
Now I want to encode JSON depends from my Data
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)
How to do that, or I need to use other structure of my data struct for each of packets?
回答1:
I'd have structures for the two main model objects, Location and Synchronization. I'd then define them to conform to some protocol where we specified how we know which "header" goes for which type of payload. And I'd then make a generic Packet that can package these two possible payloads:
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
}
}
Then you can do:
let location = Location(lat: 36.16, long: 50.36, accuracy: 5)
let packet = Packet(payload: location)
let json = try! encoder.encode(packet)
resulting in:
{
"data" : {
"lat" : 36.159999999999997,
"long" : 50.359999999999999,
"accuracy" : 5
},
"header" : "loc"
}
or
let location = Synchronization(time: 15646565455, tz: "+2", system: 5)
let packet = Packet(payload: location)
let json = try! encoder.encode(packet)
Resulting in:
{
"data" : {
"system" : 5,
"time" : 15646565455,
"tz" : "+2"
},
"header" : "syn"
}
回答2:
I recomende you to create 3 structures.
- The main going to have data structure and header structure.
Each structure has to conform to Codable protocol.
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))
Fill free to ask eny questions. Next time before you ask any question, try to google it. There is a lot of good tutorials for solving this kind of problems.
Raywanderlich tutorial
来源:https://stackoverflow.com/questions/47931129/jsonencoder-with-multiple-structures