Reputation: 33
I'm writing a socket.io
client and I'm having trouble getting the emitted data into any usable format.
My handler is:
socket.on("foriEvent") { data, ack in
print(data)
}
which prints:
[
{
"foriEvent":{
"eventType":"location",
"state":"moving",
"latitude":"60.4413407",
"longitude":"22.2476208",
"accuracy":"20",
"ts":1510653600189
}
}
]
I have a Struct
that "looks" like that data, and I would like to use something like this where the from object is of type Data
.
let decoder = JSONDecoder()
let foriEvent = try decoder.decode(ForiEvent.self, from: data)
Currently I'm using the following to get a Data object, but when I send it to decoder.decode, I get the following error message:
return try JSONSerialization.data(withJSONObject: json, options: JSONSerialization.WritingOptions.prettyPrinted)
error trying to convert data to JSON typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))
Could it be my struct? What should it look like? The Struct
looks like this right now:
struct ForiEvent : Codable {
var eventType: String?
var state : String?
var latitude: String?
var longitude : String?
var accuracy : String?
var timeStamp : CLong?
}
struct ForiData : Codable {
var foriEvent : ForiEvent?
}
Upvotes: 2
Views: 3288
Reputation: 187
Using SwiftyJSON is easiest way to handle json
Use this example
socket.on("foriEvent") { data, ack in
// because 'data' is type of [Any] so we can use 'JSON.init(AnyObject)'
let json:JSON = JSON(data[0])//JSON.init(parseJSON: cur)
// variable json is ready for use as this json["foriEvent"]
}
Upvotes: 2
Reputation: 2826
I use swiftyjson for this. It does a great job.
You haven't defined what type the data is but if it is a string which it looks like it is from the print command that you have then you can do this.
guard let dataFromString = data[0].data(using: String.Encoding.utf8, allowLossyConversion: false) else {return}
var swiftyJson:JSON!
do {
swiftyJson = try JSON(data: dataFromString)
} catch {
print("Error JSON: \(error)")
}
This will give you the data in JSON format which you can very easily parse using swiftyjson into the custom type you have outlined above. The reason that Codable might not be working is because your JSON is returned as an array of JSON.
Try this
let tempVar = swiftyJson["foriEvent"]["eventType"].string
print("test \(tempVar)")
Upvotes: 1
Reputation: 2652
I think there is no need to implement any third party (BTW I'm not againsed to SwiftyJson or any other). You can do it as:
//Here is the new struct for your ForiEvent
struct ForiEvent {
var eventType: String?
var state : String?
var latitude: String?
var longitude : String?
var accuracy : String?
var timeStamp : CLong?
init(dict: [String:Any]) {
if let obj = dict["eventType"] {
eventType = "\(obj)"
}
if let obj = dict["state"] {
state = "\(obj)"
}
if let obj = dict["latitude"] {
latitude = "\(obj)"
}
if let obj = dict["longitude"] {
longitude = "\(obj)"
}
if let obj = dict["accuracy"] {
accuracy = "\(obj)"
}
if let obj = dict["timeStamp"] as? CLong {
timeStamp = obj
}
}
}
//You data as [[String:Any]] returend from on complitionhandler
let dictArray:[[String:Any]] = [[
"foriEvent":[
"eventType" : "location",
"state":"moving",
"latitude":"60.4413407",
"longitude":"22.2476208",
"accuracy":"20",
"ts":1510653600189
]
]
]
print(dictArray)
// How to Use it:
var foriEventArray = [ForiEvent]()
for eventData in dictArray {
if let eventDict = eventData["foriEvent"] as? [String:Any] {
foriEventArray.append(ForiEvent(dict: eventDict))
}
}
print(foriEventArray)
Upvotes: 1