Skip to content

Commit c7b5fe9

Browse files
committed
Swift: Rely on Swift's Codable and configure it properly for the expected serialization
1 parent b0fdb86 commit c7b5fe9

File tree

4 files changed

+66
-31
lines changed

4 files changed

+66
-31
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Swift: Rely on Swift's Codable and configure it properly for the expected serialization ([#815](https://github.com/mozilla/glean_parser/pull/815))
6+
57
## 18.0.5
68

79
- BUGFIX: Kotlin: correctly build a serial descriptor

glean_parser/templates/swift.jinja2

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,22 @@ struct {{ obj.name|Camelize }}{{ suffix }}: EventExtras {
4444
}
4545
{% endmacro %}
4646

47-
{%- macro generate_structure(name, struct) %}
47+
{%- macro generate_structure(name, struct, toplevel) %}
4848
{%- if struct.type == "oneof" -%}
49-
enum {{ name }}: Codable, Equatable, ObjectSerialize {
49+
enum {{ name }}: Codable, Equatable {
5050
{% for ty in struct.subtypes %}
5151
case {{ty}}({{ty|structure_type_name}})
5252
{% endfor %}
5353

54-
func intoSerializedObject() -> String {
55-
switch self {
56-
{% for ty in struct.subtypes %}
57-
case .{{ty}}(let val):
58-
return val.intoSerializedObject()
59-
{% endfor %}
60-
}
61-
}
54+
func encode(to __encoder: Encoder) throws {
55+
var __container = __encoder.singleValueContainer()
56+
switch self {
57+
{% for ty in struct.subtypes %}
58+
case .{{ty}}(let __val):
59+
try __container.encode(__val)
60+
{% endfor %}
61+
}
62+
}
6263
}
6364

6465
{%- elif struct.type == "array" -%}
@@ -67,7 +68,7 @@ struct {{ obj.name|Camelize }}{{ suffix }}: EventExtras {
6768
{{ generate_structure(name ~ "Item", struct["items"]) }}
6869

6970
{%- elif struct.type == "object" -%}
70-
struct {{ name }}: Codable, Equatable, ObjectSerialize {
71+
struct {{ name }}: Codable, Equatable {% if toplevel %}, ObjectSerialize{% endif %} {
7172
{% for itemname, val in struct.properties.items() %}
7273
{%- set varname = itemname|camelize|variable_name -%}
7374
{% if val.type == "array" %}
@@ -81,26 +82,36 @@ struct {{ obj.name|Camelize }}{{ suffix }}: EventExtras {
8182
{% endif %}
8283
{% endfor %}
8384

84-
func intoSerializedObject() -> String {
85-
var __obj = [String]()
85+
enum CodingKeys: String, CodingKey {
86+
{% for itemname, val in struct.properties.items() %}
87+
{%- set varname = itemname|camelize|variable_name -%}
88+
case {{varname}} = "{{ itemname }}"
89+
{% endfor %}
90+
}
91+
92+
func encode(to encoder: Encoder) throws {
93+
var container = encoder.container(keyedBy: CodingKeys.self)
8694
{% for itemname, val in struct.properties.items() %}
87-
{%- set varname = itemname|camelize|variable_name -%}
88-
{% if val.type == "array" %}
89-
if {{varname}}.count > 0 {
90-
let {{varname}} = self.{{varname}}
91-
{% else %}
92-
if let {{varname}} = self.{{varname}} {
93-
{% endif %}
94-
var __elem = "\"{{itemname}}\":"
95-
__elem.append({{varname}}.intoSerializedObject())
96-
__obj.append(__elem)
97-
}
95+
{%- set varname = itemname|camelize|variable_name -%}
96+
{% if val.type == "array" %}
97+
if {{varname}}.count > 0 {
98+
let {{varname}} = self.{{varname}}
99+
{% else %}
100+
if let {{varname}} = self.{{varname}} {
101+
{% endif %}
102+
try container.encode({{varname}}, forKey: .{{varname}})
103+
}
98104
{% endfor %}
99-
var __json = "{"
100-
__json.append(__obj.joined(separator: ","))
101-
__json.append("}")
102-
return __json
105+
}
106+
107+
{% if toplevel %}
108+
func intoSerializedObject() -> String {
109+
let jsonEncoder = JSONEncoder()
110+
let jsonData = try! jsonEncoder.encode(self)
111+
let json = String(data: jsonData, encoding: String.Encoding.utf8)!
112+
return json
103113
}
114+
{% endif %}
104115
}
105116

106117
{% for itemname, val in struct.properties.items() %}
@@ -191,7 +202,7 @@ extension {{ namespace }} {
191202
enum {{ category.name|Camelize }} {
192203
{% for obj in category.objs.values() %}
193204
{% if obj|attr("_generate_structure") %}
194-
{{ generate_structure(obj.name|Camelize ~ "Object", obj._generate_structure) }}
205+
{{ generate_structure(obj.name|Camelize ~ "Object", obj._generate_structure, true) }}
195206
{%- endif %}
196207
{% if obj|attr("_generate_enums") %}
197208
{% for name, suffix in obj["_generate_enums"] %}

tests/data/object.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ complex.types:
3939
items:
4040
type: boolean
4141

42+
toplevel_object:
43+
type: object
44+
description: Top-level object
45+
bugs:
46+
- https://bugzilla.mozilla.org/11137353
47+
data_reviews:
48+
- http://example.com/reviews
49+
notification_emails:
50+
51+
expires: never
52+
structure:
53+
type: object
54+
properties:
55+
key1:
56+
type: string
57+
another_value:
58+
type: number
59+
sub_array:
60+
type: array
61+
items:
62+
type: number
63+
4264
oneof:
4365
type: object
4466
description: |

tests/test_swift.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,12 @@ def test_object_metric(tmp_path):
370370
assert "ObjectMetricType<ThreadsObject>" in content
371371
assert "typealias ThreadsObject = [ThreadsObjectItem]" in content
372372
assert (
373-
"struct ThreadsObjectItem: Codable, Equatable, ObjectSerialize {" in content
373+
"struct ThreadsObjectItem: Codable, Equatable {" in content
374374
)
375375
assert "var frames: ThreadsObjectItemFrames" in content
376376

377377
assert (
378-
"struct ThreadsObjectItemFramesItem: Codable, Equatable, ObjectSerialize {"
378+
"struct ThreadsObjectItemFramesItem: Codable, Equatable {"
379379
in content
380380
)
381381
assert "var moduleIndex: Int64?" in content

0 commit comments

Comments
 (0)