Skip to content

Commit 7153598

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

File tree

1 file changed

+43
-24
lines changed

1 file changed

+43
-24
lines changed

crates/target_go/src/lib.rs

+43-24
Original file line numberDiff line numberDiff line change
@@ -258,32 +258,50 @@ impl jtd_codegen::target::Target for Target {
258258

259259
writeln!(out)?;
260260
write!(out, "{}", description(&metadata, 0))?;
261-
writeln!(out, "type {} struct {{", name)?;
262-
writeln!(out, "\t{} string", tag_field_name)?;
261+
writeln!(out, "type {} interface {{", name)?;
262+
writeln!(out, "\tjson.Marshaler")?;
263+
writeln!(out, "\t{}() string", tag_field_name)?;
264+
writeln!(out, "\tis{}()", name)?;
265+
writeln!(out, "}}")?;
266+
writeln!(out)?;
267+
263268
for variant in &variants {
264-
writeln!(out)?;
265-
writeln!(out, "\t{} {}", &variant.field_name, &variant.type_name)?;
269+
writeln!(out, "func ({}) {}() string {{ return {:?} }}", variant.type_name, tag_field_name, variant.tag_value)?;
266270
}
267-
writeln!(out, "}}")?;
271+
writeln!(out)?;
268272

273+
for variant in &variants {
274+
writeln!(out, "func ({}) is{}() {{}}", variant.type_name, name)?;
275+
}
269276
writeln!(out)?;
270-
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", name)?;
271-
writeln!(out, "\tswitch v.{} {{", tag_field_name)?;
277+
272278
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)?;
279+
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", variant.type_name)?;
280+
writeln!(out, "\treturn json.Marshal(struct {{")?;
281+
writeln!(out, "\t\tT string `json:\"{}\"`", tag_json_name)?;
282+
writeln!(out, "\t\t{}", variant.type_name)?;
283+
writeln!(out, "\t}}{{")?;
284+
writeln!(out, "\t\tv.{}(),", tag_field_name)?;
285+
writeln!(out, "\t\tv,")?;
286+
writeln!(out, "\t}})")?;
287+
writeln!(out, "}}")?;
288+
writeln!(out)?;
275289
}
276-
writeln!(out, "\t}}")?;
290+
277291
writeln!(out)?;
278-
writeln!(
279-
out,
280-
"\treturn nil, fmt.Errorf(\"bad {0} value: %s\", v.{0})",
281-
tag_field_name
282-
)?;
292+
writeln!(out, "// {}Discriminator wraps the interface that it embeds. It can be", name)?;
293+
writeln!(out, "// the following types:")?;
294+
writeln!(out, "//")?;
295+
for variant in &variants {
296+
writeln!(out, "\t// - [{}] ({})", &variant.type_name, &variant.tag_value)?;
297+
}
298+
writeln!(out, "//")?;
299+
writeln!(out, "type {}Discriminator struct {{", name)?;
300+
writeln!(out, "\t{}", name)?;
283301
writeln!(out, "}}")?;
284302

285303
writeln!(out)?;
286-
writeln!(out, "func (v *{}) UnmarshalJSON(b []byte) error {{", name)?;
304+
writeln!(out, "func (v *{}Discriminator) UnmarshalJSON(b []byte) error {{", name)?;
287305
writeln!(
288306
out,
289307
"\tvar t struct {{ T string `json:\"{}\"` }}",
@@ -293,29 +311,30 @@ impl jtd_codegen::target::Target for Target {
293311
writeln!(out, "\t\treturn err")?;
294312
writeln!(out, "\t}}")?;
295313
writeln!(out)?;
314+
writeln!(out, "\tvar value {}", name)?;
296315
writeln!(out, "\tvar err error")?;
316+
writeln!(out)?;
297317
writeln!(out, "\tswitch t.T {{")?;
298318
for variant in &variants {
299319
writeln!(out, "\tcase {:?}:", variant.tag_value)?;
300-
writeln!(
301-
out,
302-
"\t\terr = json.Unmarshal(b, &v.{})",
303-
variant.field_name
304-
)?;
320+
writeln!(out, "\t\tvar v {}", variant.type_name)?;
321+
writeln!(out, "\t\terr = json.Unmarshal(b, &v)")?;
322+
writeln!(out, "\t\tvalue = v")?;
305323
}
306324
writeln!(out, "\tdefault:")?;
307325
writeln!(
308326
out,
309-
"\t\terr = fmt.Errorf(\"bad {} value: %s\", t.T)",
310-
tag_field_name
327+
"\t\terr = fmt.Errorf(\"{}: bad {} value: %q\", t.T)",
328+
name,
329+
tag_json_name
311330
)?;
312331
writeln!(out, "\t}}")?;
313332
writeln!(out)?;
314333
writeln!(out, "\tif err != nil {{")?;
315334
writeln!(out, "\t\treturn err")?;
316335
writeln!(out, "\t}}")?;
317336
writeln!(out)?;
318-
writeln!(out, "\tv.{} = t.T", tag_field_name)?;
337+
writeln!(out, "\tv.{} = value", name)?;
319338
writeln!(out, "\treturn nil")?;
320339
writeln!(out, "}}")?;
321340

0 commit comments

Comments
 (0)