Skip to content

Commit fabc8f2

Browse files
committed
Generate Go interfaces for discriminators
This commit implements jsontypedef/issues/67.
1 parent a42555d commit fabc8f2

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

crates/target_go/src/lib.rs

+39-20
Original file line numberDiff line numberDiff line change
@@ -259,27 +259,36 @@ impl jtd_codegen::target::Target for Target {
259259
writeln!(out)?;
260260
write!(out, "{}", description(&metadata, 0))?;
261261
writeln!(out, "type {} struct {{", name)?;
262-
writeln!(out, "\t{} string", tag_field_name)?;
262+
writeln!(out, "\t// Value can be the following types:")?;
263263
for variant in &variants {
264-
writeln!(out)?;
265-
writeln!(out, "\t{} {}", &variant.field_name, &variant.type_name)?;
264+
writeln!(out, "\t// - [{}] ({})", &variant.type_name, &variant.tag_value)?;
266265
}
266+
writeln!(out, "\tValue value{}", name)?;
267267
writeln!(out, "}}")?;
268268

269269
writeln!(out)?;
270-
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", name)?;
271-
writeln!(out, "\tswitch v.{} {{", tag_field_name)?;
270+
writeln!(out, "// {} returns the discriminator value for the current type.", tag_field_name)?;
271+
writeln!(out, "func (v {}) {}() string {{", name, tag_field_name)?;
272+
writeln!(out, "\tswitch value := v.Value.(type) {{")?;
272273
for variant in &variants {
273-
writeln!(out, "\tcase {:?}:", variant.tag_value)?;
274-
writeln!(out, "\t\treturn json.Marshal(struct {{ T string `json:\"{}\"`; {} }}{{ v.{}, v.{} }})", tag_json_name, variant.type_name, tag_field_name, variant.field_name)?;
274+
writeln!(out, "\tcase {}:", variant.type_name)?;
275+
writeln!(out, "\t\treturn {:?}", variant.tag_value)?;
275276
}
277+
writeln!(out, "\tdefault:")?;
278+
writeln!(out, "\t\tpanic(\"unreachable\")")?;
276279
writeln!(out, "\t}}")?;
280+
writeln!(out, "}}")?;
281+
277282
writeln!(out)?;
278-
writeln!(
279-
out,
280-
"\treturn nil, fmt.Errorf(\"bad {0} value: %s\", v.{0})",
281-
tag_field_name
282-
)?;
283+
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", name)?;
284+
writeln!(out, "\tswitch value := v.Value.(type) {{")?;
285+
for variant in &variants {
286+
writeln!(out, "\tcase {}:", variant.type_name)?;
287+
writeln!(out, "\t\treturn json.Marshal(struct {{ T string `json:\"{}\"`; {} }}{{ {:?}, value }})", tag_json_name, variant.type_name, variant.tag_value)?;
288+
}
289+
writeln!(out, "\tdefault:")?;
290+
writeln!(out, "\t\tpanic(\"unreachable\")")?;
291+
writeln!(out, "\t}}")?;
283292
writeln!(out, "}}")?;
284293

285294
writeln!(out)?;
@@ -293,32 +302,42 @@ impl jtd_codegen::target::Target for Target {
293302
writeln!(out, "\t\treturn err")?;
294303
writeln!(out, "\t}}")?;
295304
writeln!(out)?;
305+
writeln!(out, "\tvar value value{}", name)?;
296306
writeln!(out, "\tvar err error")?;
307+
writeln!(out)?;
297308
writeln!(out, "\tswitch t.T {{")?;
298309
for variant in &variants {
299310
writeln!(out, "\tcase {:?}:", variant.tag_value)?;
300-
writeln!(
301-
out,
302-
"\t\terr = json.Unmarshal(b, &v.{})",
303-
variant.field_name
304-
)?;
311+
writeln!(out, "\t\tvar v {}", variant.type_name)?;
312+
writeln!(out, "\t\terr = json.Unmarshal(b, &v)")?;
313+
writeln!(out, "\t\tvalue = v")?;
305314
}
306315
writeln!(out, "\tdefault:")?;
307316
writeln!(
308317
out,
309-
"\t\terr = fmt.Errorf(\"bad {} value: %s\", t.T)",
310-
tag_field_name
318+
"\t\terr = fmt.Errorf(\"{}: bad {} value: %q\", t.T)",
319+
name,
320+
tag_json_name
311321
)?;
312322
writeln!(out, "\t}}")?;
313323
writeln!(out)?;
314324
writeln!(out, "\tif err != nil {{")?;
315325
writeln!(out, "\t\treturn err")?;
316326
writeln!(out, "\t}}")?;
317327
writeln!(out)?;
318-
writeln!(out, "\tv.{} = t.T", tag_field_name)?;
328+
writeln!(out, "\tv.Value = value")?;
319329
writeln!(out, "\treturn nil")?;
320330
writeln!(out, "}}")?;
321331

332+
writeln!(out)?;
333+
writeln!(out, "type value{} interface {{", name)?;
334+
writeln!(out, "\tis{}()", name)?;
335+
writeln!(out, "}}")?;
336+
writeln!(out)?;
337+
for variant in &variants {
338+
writeln!(out, "func ({}) is{}() {{}}", variant.type_name, name)?;
339+
}
340+
322341
None
323342
}
324343

0 commit comments

Comments
 (0)