Skip to content

Commit 5423dc5

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

File tree

1 file changed

+92
-25
lines changed

1 file changed

+92
-25
lines changed

crates/target_go/src/lib.rs

+92-25
Original file line numberDiff line numberDiff line change
@@ -259,27 +259,12 @@ 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)?;
263-
for variant in &variants {
264-
writeln!(out)?;
265-
writeln!(out, "\t{} {}", &variant.field_name, &variant.type_name)?;
266-
}
262+
writeln!(out, "\tValue I{} `json:\"-\"`", name)?;
267263
writeln!(out, "}}")?;
268264

269265
writeln!(out)?;
270266
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", name)?;
271-
writeln!(out, "\tswitch v.{} {{", tag_field_name)?;
272-
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)?;
275-
}
276-
writeln!(out, "\t}}")?;
277-
writeln!(out)?;
278-
writeln!(
279-
out,
280-
"\treturn nil, fmt.Errorf(\"bad {0} value: %s\", v.{0})",
281-
tag_field_name
282-
)?;
267+
writeln!(out, "\treturn json.Marshal(v.Value)")?;
283268
writeln!(out, "}}")?;
284269

285270
writeln!(out)?;
@@ -293,32 +278,114 @@ impl jtd_codegen::target::Target for Target {
293278
writeln!(out, "\t\treturn err")?;
294279
writeln!(out, "\t}}")?;
295280
writeln!(out)?;
281+
writeln!(out, "\tvar value I{}", name)?;
296282
writeln!(out, "\tvar err error")?;
283+
writeln!(out)?;
297284
writeln!(out, "\tswitch t.T {{")?;
298285
for variant in &variants {
299286
writeln!(out, "\tcase {:?}:", variant.tag_value)?;
300-
writeln!(
301-
out,
302-
"\t\terr = json.Unmarshal(b, &v.{})",
303-
variant.field_name
304-
)?;
287+
writeln!(out, "\t\tvar v {}", variant.type_name)?;
288+
writeln!(out, "\t\terr = json.Unmarshal(b, &v)")?;
289+
writeln!(out, "\t\tvalue = v")?;
305290
}
306291
writeln!(out, "\tdefault:")?;
307292
writeln!(
308293
out,
309-
"\t\terr = fmt.Errorf(\"bad {} value: %s\", t.T)",
310-
tag_field_name
294+
"\t\terr = fmt.Errorf(\"{}: bad {} value: %q\", t.T)",
295+
name, tag_json_name
311296
)?;
312297
writeln!(out, "\t}}")?;
313298
writeln!(out)?;
314299
writeln!(out, "\tif err != nil {{")?;
315300
writeln!(out, "\t\treturn err")?;
316301
writeln!(out, "\t}}")?;
317302
writeln!(out)?;
318-
writeln!(out, "\tv.{} = t.T", tag_field_name)?;
303+
writeln!(out, "\tv.Value = value")?;
319304
writeln!(out, "\treturn nil")?;
320305
writeln!(out, "}}")?;
321306

307+
writeln!(out)?;
308+
writeln!(
309+
out,
310+
"// I{} is an interface type that {} types implement.",
311+
name, name
312+
)?;
313+
writeln!(out, "// It can be the following types:")?;
314+
writeln!(out, "//")?;
315+
for variant in &variants {
316+
writeln!(
317+
out,
318+
"// - [{}] ({})",
319+
&variant.type_name, &variant.tag_value
320+
)?;
321+
}
322+
writeln!(out, "//")?;
323+
writeln!(out, "type I{} interface {{", name)?;
324+
writeln!(out, "\t{}() string", tag_field_name)?;
325+
writeln!(out, "\tis{}()", name)?;
326+
writeln!(out, "}}")?;
327+
writeln!(out)?;
328+
329+
for variant in &variants {
330+
writeln!(
331+
out,
332+
"func ({}) {}() string {{ return {:?} }}",
333+
variant.type_name, tag_field_name, variant.tag_value
334+
)?;
335+
}
336+
writeln!(out)?;
337+
338+
for variant in &variants {
339+
writeln!(out, "func ({}) is{}() {{}}", variant.type_name, name)?;
340+
}
341+
writeln!(out)?;
342+
343+
for variant in &variants {
344+
writeln!(
345+
out,
346+
"func (v {}) MarshalJSON() ([]byte, error) {{",
347+
variant.type_name
348+
)?;
349+
writeln!(out, "\ttype Alias {}", variant.type_name)?;
350+
writeln!(out, "\treturn json.Marshal(struct {{")?;
351+
writeln!(out, "\t\tT string `json:\"{}\"`", tag_json_name)?;
352+
writeln!(out, "\t\tAlias")?;
353+
writeln!(out, "\t}}{{")?;
354+
writeln!(out, "\t\tv.{}(),", tag_field_name)?;
355+
writeln!(out, "\t\tAlias(v),")?;
356+
writeln!(out, "\t}})")?;
357+
writeln!(out, "}}")?;
358+
writeln!(out)?;
359+
360+
writeln!(
361+
out,
362+
"func (v *{}) UnmarshalJSON(b []byte) error {{",
363+
variant.type_name
364+
)?;
365+
writeln!(out, "\ttype Alias {}", variant.type_name)?;
366+
writeln!(out, "\tvar a struct {{")?;
367+
writeln!(out, "\t\tT string `json:\"{}\"`", tag_json_name)?;
368+
writeln!(out, "\t\tAlias")?;
369+
writeln!(out, "\t}}")?;
370+
writeln!(out)?;
371+
writeln!(out, "\tif err := json.Unmarshal(b, &a); err != nil {{")?;
372+
writeln!(out, "\t\treturn err")?;
373+
writeln!(out, "\t}}")?;
374+
writeln!(out)?;
375+
writeln!(out, "\tif a.T != {:?} {{", variant.tag_value)?;
376+
writeln!(
377+
out,
378+
"\t\treturn fmt.Errorf(\"{}: bad {} value: %q\", a.T)",
379+
variant.type_name, tag_json_name
380+
)?;
381+
writeln!(out, "\t}}")?;
382+
writeln!(out)?;
383+
writeln!(out, "\t*v = {}(a.Alias)", variant.type_name)?;
384+
writeln!(out, "\treturn nil")?;
385+
writeln!(out, "}}")?;
386+
writeln!(out)?;
387+
}
388+
322389
None
323390
}
324391

0 commit comments

Comments
 (0)