From 078825b4eb8405bb641639e48aa07c14a81c24c0 Mon Sep 17 00:00:00 2001 From: fondoger Date: Mon, 17 Apr 2023 13:06:52 +0800 Subject: [PATCH] [dart-gen] Support Null-safe and omitempty json tag (#3134) --- tools/goctl/api/dartgen/gendata.go | 24 ++++++++++--- tools/goctl/api/dartgen/util.go | 54 ++++++++++++++++++++++++++++-- tools/goctl/api/dartgen/vars.go | 3 ++ 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/tools/goctl/api/dartgen/gendata.go b/tools/goctl/api/dartgen/gendata.go index e2ff03c2..92391497 100644 --- a/tools/goctl/api/dartgen/gendata.go +++ b/tools/goctl/api/dartgen/gendata.go @@ -42,15 +42,29 @@ class {{.Name}} { {{range .Members}} required this.{{lowCamelCase .Name}}, {{end}}}{{end}}); factory {{.Name}}.fromJson(Map m) { - return {{.Name}}({{range .Members}} - {{lowCamelCase .Name}}: {{if isDirectType .Type.Name}}m['{{getPropertyFromMember .}}'] - {{else if isClassListType .Type.Name}}(m['{{getPropertyFromMember .}}'] as List).map((i) => {{getCoreType .Type.Name}}.fromJson(i)).toList() - {{else}}{{.Type.Name}}.fromJson(m['{{getPropertyFromMember .}}']){{end}},{{end}} + return {{.Name}}( + {{range .Members}} + {{lowCamelCase .Name}}: {{appendNullCoalescing .}} + {{if isDirectType .Type.Name}} + m['{{getPropertyFromMember .}}'] {{appendDefaultEmptyValue .Type.Name}} + {{else if isClassListType .Type.Name}} + ((m['{{getPropertyFromMember .}}'] {{appendDefaultEmptyValue .Type.Name}}) as List).map((i) => {{getCoreType .Type.Name}}.fromJson(i)).toList() + {{else}} + {{.Type.Name}}.fromJson(m['{{getPropertyFromMember .}}']){{end}} + ,{{end}} ); } Map toJson() { return { {{range .Members}} - '{{getPropertyFromMember .}}': {{if isDirectType .Type.Name}}{{lowCamelCase .Name}}{{else if isClassListType .Type.Name}}{{lowCamelCase .Name}}.map((i) => i.toJson()){{else}}{{lowCamelCase .Name}}.toJson(){{end}},{{end}} + '{{getPropertyFromMember .}}': + {{if isDirectType .Type.Name}} + {{lowCamelCase .Name}} + {{else if isClassListType .Type.Name}} + {{lowCamelCase .Name}}{{if isNullableType .Type.Name}}?{{end}}.map((i) => i.toJson()) + {{else}} + {{lowCamelCase .Name}}{{if isNullableType .Type.Name}}?{{end}}.toJson() + {{end}} + ,{{end}} }; } } diff --git a/tools/goctl/api/dartgen/util.go b/tools/goctl/api/dartgen/util.go index d69d6518..81d32fcd 100644 --- a/tools/goctl/api/dartgen/util.go +++ b/tools/goctl/api/dartgen/util.go @@ -74,6 +74,52 @@ func isClassListType(s string) bool { return strings.HasPrefix(s, "List<") && !isAtomicType(getCoreType(s)) } +func isMapType(s string) bool { + return strings.HasPrefix(s, "Map<") +} + +// Only interface types are nullable +func isNullableType(s string) bool { + return strings.HasSuffix(s, "?") +} + +func appendNullCoalescing(member spec.Member) string { + if isNullableType(member.Type.Name()) { + return "m['" + getPropertyFromMember(member) + "'] == null ? null : " + } + return "" +} + +// To be compatible with omitempty tags in Golang +// Only set default value for non-nullable types +func appendDefaultEmptyValue(s string) string { + if isNullableType(s) { + return "" + } + + if isAtomicType(s) { + switch s { + case "String": + return `?? ""` + case "int": + return "?? 0" + case "double": + return "?? 0.0" + case "bool": + return "?? false" + default: + panic(errors.New("unknown atomic type")) + } + } + if isListType(s) { + return "?? []" + } + if isMapType(s) { + return "?? {}" + } + return "" +} + func getCoreType(s string) string { if isAtomicType(s) { return s @@ -139,9 +185,13 @@ func specTypeToDart(tp spec.Type) (string, error) { } return fmt.Sprintf("List<%s>", valueType), nil case spec.InterfaceType: - return "Object", nil + return "Object?", nil case spec.PointerType: - return specTypeToDart(v.Type) + valueType, err := specTypeToDart(v.Type) + if err != nil { + return "", err + } + return fmt.Sprintf("%s?", valueType), nil } return "", errors.New("unsupported primitive type " + tp.Name()) diff --git a/tools/goctl/api/dartgen/vars.go b/tools/goctl/api/dartgen/vars.go index d923820f..a61ff0cc 100644 --- a/tools/goctl/api/dartgen/vars.go +++ b/tools/goctl/api/dartgen/vars.go @@ -8,6 +8,9 @@ var funcMap = template.FuncMap{ "isDirectType": isDirectType, "isNumberType": isNumberType, "isClassListType": isClassListType, + "isNullableType": isNullableType, + "appendNullCoalescing": appendNullCoalescing, + "appendDefaultEmptyValue": appendDefaultEmptyValue, "getCoreType": getCoreType, "lowCamelCase": lowCamelCase, "normalizeHandlerName": normalizeHandlerName,