1

I'm having trouble translating my models into dictionaries. My models inherit from Codable and when using JSONSerialization I get a dictionary with the form:

(...,"sensors": <__NSArrayI 0x1105324f0>( {
accx = "-0.002471923828125";
accy = "0.011444091796875";
accz = "-1.013595581054688";
gyrox = "-0.029818882093399213";
gyroy = "0.028939506301455049";
gyroz = "0.0044943506556177227"; }, ...)  

(Note that my keys are not as string but the values are)

when in fact a want this:

(..., "sensors": [ {
"accx" = -0.002471923828125;
"accy" = 0.011444091796875;
"accz" = -1.013595581054688;
"gyrox" = -0.029818882093399213;
"gyroy" = 0.028939506301455049;
"gyroz" = 0.0044943506556177227;} ], ... )

My models are:

class Event: NSObject, Codable {

var latitude: Double?
var longitude: Double?
var speed: Double?
var date: String?
var type: String?
var sensors: [Sensor] = []

}

class Sensor: NSObject, Codable {
   var accx: Double?
   var accy: Double?
   var accz: Double?
   var gyrox: Double?
   var gyroy: Double?
  var gyroz: Double?
}

Im using this to transform into dictionary:

extension Encodable {

var dictionary: [String: Any]? {
    do{

        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        guard let data = try? encoder.encode(self) else { return nil }
        let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
        print(json)
        return json
    } catch {
        return nil
    }
}
}

I'm stuck with this and I do not know if I'm going down the right path. Should I change the way I organize this dictionary?

1 Answers1

1

You are looking at the result of NSDictionary.description there, and the result of NSDictionary.description is not JSON and not necessarily an accurate representation of the contained objects.

There is no actual problem with the decoding. Example:

Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance.
  1> import Foundation
  2> let json = "{ \"sensors\": [ { \"accx\": 0.011444091796875 } ] }"
json: String = "{ \"sensors\": [ { \"accx\": 0.011444091796875 } ] }"
  3> let d = try! JSONSerialization.jsonObject(with: json.data(using: .utf8)!, options: []) as! [String: Any] 
d: [String : Any] = 1 key/value pair {
  [0] = {
    key = "sensors"
    value = {
      payload_data_0 = 0x0000000100111ad0
      payload_data_1 = 0x0000000000000000
      payload_data_2 = 0x0000000000000000
      instance_type = 0x00000001014179c8 libswiftCore.dylib`InitialAllocationPool + 4888
    }
  }
}

When we print the dictionary returned by JSONSerialization, we see the number in quotes:

  4> print(d)
["sensors": <__NSSingleObjectArrayI 0x100111ad0>(
{
    accx = "0.011444091796875";
}
)
]

But when we actually extract the number from the nested containers, it is actually a Double:

  5> ((d["sensors"] as! [Any])[0] as! [String: Any])["accx"] as! Double
$R0: Double = 0.011444091796875

The moral of the story: Don't expect an object's description to be an accurate serialization of its value. If you need an accurate serialization, convert the object to JSON or a property list, or inspect it in the debugger.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848