Bonjour, j'ai trouvé une bonne solution sans tableau à partir d' ici fonctionne OK
@propertyWrapper struct EncodablePointsArray: Encodable { var wrappedValue: [CGPoint] enum CodingKeys: CodingKey { ????? } func encode(to encoder: Encoder) throws { ?????? } } struct Foo2: Encodable { @EncodablePointsArray var pt: [CGPoint] = [CGPoint] var other = "zxcv" } let foo2 = Foo2() let encoded = try! JSONEncoder().encode(foo2) print(String(bytes: encoded, encoding: .utf8) ?? "nil") // I wold like output like : {"ArrayPointsâ:[{âxâ:1.1,âyâ:1.2},{âxâ:2.1,âyâ:3.4}]},"other":"zxcv"}
S'il vous plaît, je voudrais la solution similaire avec tableau, si quelqu'un sait s'il vous plaît aidez-moi. Je voudrais quelque chose comme:
@propertyWrapper struct EncodablePoint: Encodable { var wrappedValue: CGPoint enum CodingKeys: CodingKey { case x case y } func encode(to encoder: Encoder) throws { var c = encoder.container(keyedBy: CodingKeys.self) try c.encode(wrappedValue.x, forKey: .x) try c.encode(wrappedValue.y, forKey: .y) } } //usage: struct Foo: Encodable { @EncodablePoint var pt: CGPoint = CGPoint(x: 123, y: 456) var other = "zxcv" } let foo = Foo() let encoded = try! JSONEncoder().encode(foo) print(String(bytes: encoded, encoding: .utf8) ?? "nil") // {"pt":{"x":123,"y":456},"other":"zxcv"}
3 Réponses :
L'utilisation des fonctions unkeyedContainer () et nestedContainer (keyedBy :) fera l'affaire:
{ "pt": [ { "x": 1.1000000000000001, "y": 1.2 }, { "x": 2.1000000000000001, "y": 3.3999999999999999 } ], "other": "zxcv" }
En utilisant votre exemple:
struct Foo2: Encodable { @EncodablePointsArray var pt: [CGPoint] = [CGPoint(x: 1.1, y: 1.2), CGPoint(x: 2.1, y: 3.4)] var other = "zxcv" } let foo2 = Foo2() do { let encoded = try JSONEncoder().encode(foo2) print(String(bytes: encoded, encoding: .utf8) ?? "nil") } catch { print(error) }
Cela aura comme résultat ceci:
@propertyWrapper struct EncodablePointsArray: Encodable { var wrappedValue: [CGPoint] enum CodingKeys: CodingKey { case x case y } func encode(to encoder: Encoder) throws { var unkeyedContainer = encoder.unkeyedContainer() try wrappedValue.forEach { var container = unkeyedContainer.nestedContainer(keyedBy: CodingKeys.self) try container.encode($0.x, forKey: .x) try container.encode($0.y, forKey: .y) } } }
EncodablePoint
agit ici comme un wrapper pour CGPoint
, donc du point de vue du client, EncodablePoint
est un nouveau type avec la propriété CGPoint
.
S'il est utilisé comme wrapper de propriété, il agit comme un tableau de CGPoint
. Mais après l'encodage, il le transforme en un objet personnalisé avec des coordonnées x
et y
.
En fonction des résultats que vous souhaitez obtenir après le décodage d'un tel objet, il existe deux options ici.
EncodablePoint
encodage d' EncodablePoint
Construisons un wrapper de propriété comme celui-ci
{"pt":{"values":[[123,456],[789,123],[456,789]]},"other":"zxcv"}
Ensuite, le client du wrapper doit créer des instances d' EncodablePoint
@propertyWrapper struct EncodablePointArray: Encodable { var wrappedValue: [CGPoint] }
Un décodage qui vous donnera les résultats que vous vouliez
struct Points: Encodable { @EncodablePointArray var pt: [CGPoint] = [ CGPoint(x: 123, y: 456), CGPoint(x: 789, y: 123), CGPoint(x: 456, y: 789) ] var other = "zxcv" }
Mais je pense que vous voulez utiliser un tableau de CGPoint
, alors ...
CGPoint
encodage de CGPoint
Si vous souhaitez utiliser des CGPoint
directement comme ceci
{"pt":{"values":[{"x":123,"y":456},{"x":789,"y":123},{"x":456,"y":789}]},"other":"zxcv"}
Vous devez construire votre wrapper avec CGPoint
s
struct Points: Encodable { @EncodablePointArray var pt: [EncodablePoint] = [ EncodablePoint(wrappedValue: CGPoint(x: 123, y: 456)), EncodablePoint(wrappedValue: CGPoint(x: 789, y: 123)), EncodablePoint(wrappedValue: CGPoint(x: 456, y: 789)) ] var other = "zxcv" }
Mais la chaîne décodée sera différente:
@propertyWrapper struct EncodablePointArray: Encodable { var wrappedValue: [EncodablePoint] }
Vous partez d'informations désuètes. [CGPoint]
est Codable
sans aucune extension maintenant.
struct Foo2: Encodable { var pt: [CGPoint] = [] var other = "zxcv" }
Si vous avez réellement besoin d'un wrapper, veuillez poster le code qui le requiert. Votre question suggère que vous n'avez pas besoin de wrapper.
Bien que cela soit vrai, ce n'est pas ce que demande OP. L'encodage Foo2
aura comme résultat ce {"pt":[[1.1,1.2],[2.1,3.4]],"other":"zxcv"}
. Clairement, OP demande quelque chose comme ceci {"pt":[{"x":1.1,"y":1.2},{"x":2.1,"y":3.4}]},"other":"zxcv"}