问题
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