0

CGSize is encoded to an array by default. I would like to encode it to [String: Float] (i.e. ["width": 10, "height": 20]). Is there a way to override the default encoding/decoding behavior? Of course, as a workaround, I can define my own Dimension type and use that instead. I am just curious to know.

Jack Guo
  • 3,959
  • 8
  • 39
  • 60
  • What encoder you are using? – Mojtaba Hosseini Oct 18 '20 at 21:29
  • you probably meant `{"width": 10, "height": 20}` – Leo Dabus Oct 18 '20 at 21:40
  • @LeoDabus I see the comment is now gone, but for posterity: I wouldn't recommend that last approach (I alluded to it in my answer but didn't want to spell out the details) — it's really fragile, and works only in your own module; other modules won't necessarily see that method (esp. modules you have a dependency on), and you can silently get mixed encodings. – Itai Ferber Oct 18 '20 at 22:38
  • @ItaiFerber ok thanks – Leo Dabus Oct 18 '20 at 22:39

1 Answers1

1

There is no supported way to outright override the encoding format for a given type you don't own; there are hacks that you can apply to override some types within your own module, but they're fragile and not worth employing.

If you use a 3rd-party encoder/decoder combo that isn't Foundation.JSONEncoder/Foundation.JSONDecoder, it may offer an override facility similar to encoding/decoding strategies supported by Foundation, but that is dependent on the tools you're using.

The "official" way to do this would be to either wrap CGSize in a type you do own (as you suggest) and implement init(from:)/encode(to:) there, or override init(from:)/encode(to:) for all of the types that use CGSize (but this can get pretty tedious).

Itai Ferber
  • 28,308
  • 5
  • 77
  • 83
  • Thanks! A quick followup question, what's the advantage of wrapping it instead of just replacing it with something like `{width: Double, height: Double}`? Is it to avoid duplicate implementations that becomes a bigger issue for types not as simple as `CGSize`? – Jack Guo Oct 18 '20 at 21:52
  • Yep, exactly. `CGSize` might not see a huge win, but a type like [`CGAffineTransform`](https://developer.apple.com/documentation/coregraphics/cgaffinetransform) is a bit more annoying to recreate. The other benefit is interoperability with other APIs that take or vend `CGSize` so you don't have to recreate them to take `Dimension`. – Itai Ferber Oct 18 '20 at 22:36