From f342c3201fe02dc7979db3a5cd00e5d9c6a5c34b Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Thu, 21 Apr 2016 17:32:55 +0800 Subject: [PATCH 01/15] Handle JS Date --- typescriptify/typescriptify.go | 62 ++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index e7b5269..a314507 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -10,6 +10,8 @@ import ( "time" ) +var TimeType = reflect.TypeOf(time.Now()) + type TypeScriptify struct { Prefix string Suffix string @@ -17,10 +19,10 @@ type TypeScriptify struct { CreateFromMethod bool BackupExtension string // If empty no backup - golangTypes []reflect.Type - types map[reflect.Kind]string + golangTypes []reflect.Type + types map[reflect.Kind]string - // throwaway, used when converting + // throwaway, used when converting alreadyConverted map[reflect.Type]bool } @@ -99,7 +101,7 @@ func (this *TypeScriptify) Convert(customCode map[string]string) (string, error) if err != nil { return "", err } - result += "\n" + strings.Trim(typeScriptCode, " "+this.Indent+"\r\n") + result += "\n" + strings.Trim(typeScriptCode, " " + this.Indent + "\r\n") } return result, nil } @@ -204,12 +206,16 @@ func (this TypeScriptify) ConvertToFile(fileName string) error { } func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[string]string) (string, error) { - if _, found := this.alreadyConverted[typeOf]; found { // Already converted + if typeOf == TimeType { + return "", nil + } + if _, found := this.alreadyConverted[typeOf]; found { + // Already converted return "", nil } entityName := fmt.Sprintf("%s%s%s", this.Prefix, this.Suffix, typeOf.Name()) - result := fmt.Sprintf("class %s {\n", entityName) + result := fmt.Sprintf("export class %s {\n", entityName) builder := typeScriptClassBuilder{ types: this.types, indent: this.Indent, @@ -224,28 +230,44 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin if len(jsonTagParts) > 0 { jsonFieldName = strings.Trim(jsonTagParts[0], this.Indent) } + } else { + if field.Name != "" { + jsonFieldName = field.Name + } else { + jsonFieldName = field.Type.Name() + } } + fmt.Println("jsonFieldName", jsonFieldName) if len(jsonFieldName) > 0 && jsonFieldName != "-" { var err error - if field.Type.Kind() == reflect.Struct { // Struct: + if field.Type.Kind() == reflect.Struct { + // Struct: typeScriptChunk, err := this.convertType(field.Type, customCode) if err != nil { return "", err } result = typeScriptChunk + "\n" + result - builder.AddStructField(jsonFieldName, field.Type.Name()) - } else if field.Type.Kind() == reflect.Slice { // Slice: - if field.Type.Elem().Kind() == reflect.Struct { // Slice of structs: + fieldTypeName := field.Type.Name() + if field.Type == TimeType { + fieldTypeName = "Date" + } + builder.AddStructField(jsonFieldName, fieldTypeName) + } else if field.Type.Kind() == reflect.Slice { + // Slice: + if field.Type.Elem().Kind() == reflect.Struct { + // Slice of structs: typeScriptChunk, err := this.convertType(field.Type.Elem(), customCode) if err != nil { return "", err } result = typeScriptChunk + "\n" + result builder.AddArrayOfStructsField(jsonFieldName, field.Type.Elem().Name()) - } else { // Slice of simple fields: + } else { + // Slice of simple fields: err = builder.AddSimpleArrayField(jsonFieldName, field.Type.Elem().Name(), field.Type.Elem().Kind()) } - } else { // Simple field: + } else { + // Simple field: err = builder.AddSimpleField(jsonFieldName, field.Type.Name(), field.Type.Kind()) } if err != nil { @@ -265,7 +287,9 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin if customCode != nil { code := customCode[entityName] - result += this.Indent + "//[" + entityName + ":]\n" + code + "\n\n" + this.Indent + "//[end]\n" + if code != "" { + result += this.Indent + "//[" + entityName + ":]\n" + code + "\n\n" + this.Indent + "//[end]\n" + } } result += "}" @@ -306,10 +330,18 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string) { this.fields += fmt.Sprintf("%s%s: %s;\n", this.indent, fieldName, fieldType) - this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s.createFrom(source[\"%s\"]) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldType, fieldName) + createCall := fieldType + ".createFrom" + if fieldType == "Date" { + createCall = "new Date" + } + this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null;\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) } func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType string) { this.fields += fmt.Sprintf("%s%s: %s[];\n", this.indent, fieldName, fieldType) - this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s.createFrom(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, fieldType) + createCall := fieldType + ".createFrom" + if fieldType == "Date" { + createCall = "new Date" + } + this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) } From 3cea59b20562a6605f759332da1bf582170ba8d5 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Thu, 21 Apr 2016 18:26:42 +0800 Subject: [PATCH 02/15] handle pointer type --- typescriptify/typescriptify.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index a314507..c7d6326 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -225,6 +225,10 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin for _, field := range fields { jsonTag := field.Tag.Get("json") jsonFieldName := "" + fieldType := field.Type + if fieldType.Kind() == reflect.Ptr { + fieldType = field.Type.Elem() + } if len(jsonTag) > 0 { jsonTagParts := strings.Split(jsonTag, ",") if len(jsonTagParts) > 0 { @@ -234,41 +238,41 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin if field.Name != "" { jsonFieldName = field.Name } else { - jsonFieldName = field.Type.Name() + jsonFieldName = fieldType.Name() } } fmt.Println("jsonFieldName", jsonFieldName) if len(jsonFieldName) > 0 && jsonFieldName != "-" { var err error - if field.Type.Kind() == reflect.Struct { + if fieldType.Kind() == reflect.Struct { // Struct: - typeScriptChunk, err := this.convertType(field.Type, customCode) + typeScriptChunk, err := this.convertType(fieldType, customCode) if err != nil { return "", err } result = typeScriptChunk + "\n" + result - fieldTypeName := field.Type.Name() - if field.Type == TimeType { + fieldTypeName := fieldType.Name() + if fieldType == TimeType { fieldTypeName = "Date" } builder.AddStructField(jsonFieldName, fieldTypeName) - } else if field.Type.Kind() == reflect.Slice { + } else if fieldType.Kind() == reflect.Slice { // Slice: - if field.Type.Elem().Kind() == reflect.Struct { + if fieldType.Elem().Kind() == reflect.Struct { // Slice of structs: - typeScriptChunk, err := this.convertType(field.Type.Elem(), customCode) + typeScriptChunk, err := this.convertType(fieldType.Elem(), customCode) if err != nil { return "", err } result = typeScriptChunk + "\n" + result - builder.AddArrayOfStructsField(jsonFieldName, field.Type.Elem().Name()) + builder.AddArrayOfStructsField(jsonFieldName, fieldType.Elem().Name()) } else { // Slice of simple fields: - err = builder.AddSimpleArrayField(jsonFieldName, field.Type.Elem().Name(), field.Type.Elem().Kind()) + err = builder.AddSimpleArrayField(jsonFieldName, fieldType.Elem().Name(), fieldType.Elem().Kind()) } } else { // Simple field: - err = builder.AddSimpleField(jsonFieldName, field.Type.Name(), field.Type.Kind()) + err = builder.AddSimpleField(jsonFieldName, fieldType.Name(), fieldType.Kind()) } if err != nil { return "", err From e7035281af2ff39bd810476e6cec2bdfecb6c1e0 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Sat, 30 Apr 2016 12:37:58 +0800 Subject: [PATCH 03/15] for Date type, just keep as string type --- typescriptify/typescriptify.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index c7d6326..ec08cef 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -253,7 +253,8 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin result = typeScriptChunk + "\n" + result fieldTypeName := fieldType.Name() if fieldType == TimeType { - fieldTypeName = "Date" + //fieldTypeName = "Date" + fieldTypeName = "string" } builder.AddStructField(jsonFieldName, fieldTypeName) } else if fieldType.Kind() == reflect.Slice { @@ -336,7 +337,7 @@ func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string) this.fields += fmt.Sprintf("%s%s: %s;\n", this.indent, fieldName, fieldType) createCall := fieldType + ".createFrom" if fieldType == "Date" { - createCall = "new Date" + createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... } this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null;\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) } @@ -345,7 +346,7 @@ func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType this.fields += fmt.Sprintf("%s%s: %s[];\n", this.indent, fieldName, fieldType) createCall := fieldType + ".createFrom" if fieldType == "Date" { - createCall = "new Date" + createCall = "" } this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) } From 945b7ced5ab543c89fc19f71c20888497b96a265 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Sat, 30 Apr 2016 13:00:35 +0800 Subject: [PATCH 04/15] fix --- typescriptify/typescriptify.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index ec08cef..6772857 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -336,7 +336,7 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string) { this.fields += fmt.Sprintf("%s%s: %s;\n", this.indent, fieldName, fieldType) createCall := fieldType + ".createFrom" - if fieldType == "Date" { + if fieldType == "Date" || fieldType == "string" { createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... } this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null;\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) @@ -345,7 +345,7 @@ func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string) func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType string) { this.fields += fmt.Sprintf("%s%s: %s[];\n", this.indent, fieldName, fieldType) createCall := fieldType + ".createFrom" - if fieldType == "Date" { + if fieldType == "Date" || fieldType == "string" { createCall = "" } this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) From e01ea5d7917a0df816fead1757345461d1da9773 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Wed, 11 May 2016 16:49:50 +0800 Subject: [PATCH 05/15] support slice of pointer --- .gitignore | 2 ++ typescriptify/typescriptify.go | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 5381f39..511456b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.backup tmp_* tags + +.idea/ diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 6772857..fbd90cd 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -19,10 +19,10 @@ type TypeScriptify struct { CreateFromMethod bool BackupExtension string // If empty no backup - golangTypes []reflect.Type - types map[reflect.Kind]string + golangTypes []reflect.Type + types map[reflect.Kind]string - // throwaway, used when converting + // throwaway, used when converting alreadyConverted map[reflect.Type]bool } @@ -101,7 +101,7 @@ func (this *TypeScriptify) Convert(customCode map[string]string) (string, error) if err != nil { return "", err } - result += "\n" + strings.Trim(typeScriptCode, " " + this.Indent + "\r\n") + result += "\n" + strings.Trim(typeScriptCode, " "+this.Indent+"\r\n") } return result, nil } @@ -259,17 +259,22 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin builder.AddStructField(jsonFieldName, fieldTypeName) } else if fieldType.Kind() == reflect.Slice { // Slice: - if fieldType.Elem().Kind() == reflect.Struct { + elemType := fieldType.Elem() + if elemType.Kind() == reflect.Ptr { + fmt.Println("Ptr type", fieldType) + elemType = elemType.Elem() + } + if elemType.Kind() == reflect.Struct { // Slice of structs: - typeScriptChunk, err := this.convertType(fieldType.Elem(), customCode) + typeScriptChunk, err := this.convertType(elemType, customCode) if err != nil { return "", err } result = typeScriptChunk + "\n" + result - builder.AddArrayOfStructsField(jsonFieldName, fieldType.Elem().Name()) + builder.AddArrayOfStructsField(jsonFieldName, elemType.Name()) } else { // Slice of simple fields: - err = builder.AddSimpleArrayField(jsonFieldName, fieldType.Elem().Name(), fieldType.Elem().Kind()) + err = builder.AddSimpleArrayField(jsonFieldName, elemType.Name(), elemType.Kind()) } } else { // Simple field: From b8946f79723f3ba8e969771835954b0d578d8c10 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Wed, 11 May 2016 17:12:49 +0800 Subject: [PATCH 06/15] support anonymous struct type --- typescriptify/typescriptify.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index fbd90cd..3d9460a 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -205,7 +205,7 @@ func (this TypeScriptify) ConvertToFile(fileName string) error { return nil } -func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[string]string) (string, error) { +func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[string]string, customName ...string) (string, error) { if typeOf == TimeType { return "", nil } @@ -214,7 +214,13 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin return "", nil } + this.alreadyConverted[typeOf] = true + entityName := fmt.Sprintf("%s%s%s", this.Prefix, this.Suffix, typeOf.Name()) + if len(customName) > 0 { + entityName = fmt.Sprintf("%s%s%s", this.Prefix, this.Suffix, customName[0]) + } + result := fmt.Sprintf("export class %s {\n", entityName) builder := typeScriptClassBuilder{ types: this.types, @@ -246,12 +252,15 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin var err error if fieldType.Kind() == reflect.Struct { // Struct: - typeScriptChunk, err := this.convertType(fieldType, customCode) + fieldTypeName := fieldType.Name() + if fieldTypeName == "" { + fieldTypeName = "A_" + entityName + "_" + jsonFieldName + } + typeScriptChunk, err := this.convertType(fieldType, customCode, fieldTypeName) if err != nil { return "", err } result = typeScriptChunk + "\n" + result - fieldTypeName := fieldType.Name() if fieldType == TimeType { //fieldTypeName = "Date" fieldTypeName = "string" @@ -304,8 +313,6 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin result += "}" - this.alreadyConverted[typeOf] = true - return result, nil } From ea4acfbd3fdb6aadc22142c182031396401cd8e6 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Wed, 11 May 2016 20:01:58 +0800 Subject: [PATCH 07/15] fix anonymous struct --- typescriptify/typescriptify.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 3d9460a..7e263cf 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -209,12 +209,17 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin if typeOf == TimeType { return "", nil } - if _, found := this.alreadyConverted[typeOf]; found { - // Already converted - return "", nil - } - this.alreadyConverted[typeOf] = true + isAnonymousStruct := len(customName) > 0 && customName[0] != typeOf.Name() + + if !isAnonymousStruct { + if _, found := this.alreadyConverted[typeOf]; found { + // Already converted + return "", nil + } + + this.alreadyConverted[typeOf] = true + } entityName := fmt.Sprintf("%s%s%s", this.Prefix, this.Suffix, typeOf.Name()) if len(customName) > 0 { @@ -254,7 +259,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin // Struct: fieldTypeName := fieldType.Name() if fieldTypeName == "" { - fieldTypeName = "A_" + entityName + "_" + jsonFieldName + fieldTypeName = "__" + entityName + "_" + jsonFieldName } typeScriptChunk, err := this.convertType(fieldType, customCode, fieldTypeName) if err != nil { From 6d01136c323512b46e9d7b9de6edf17dde1ce801 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Thu, 12 May 2016 14:24:11 +0800 Subject: [PATCH 08/15] support interface{} and map, convert exported fields only --- typescriptify/typescriptify.go | 43 +++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 7e263cf..ec8d7ce 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -8,6 +8,8 @@ import ( "reflect" "strings" "time" + "unicode" + "unicode/utf8" ) var TimeType = reflect.TypeOf(time.Now()) @@ -19,10 +21,10 @@ type TypeScriptify struct { CreateFromMethod bool BackupExtension string // If empty no backup - golangTypes []reflect.Type - types map[reflect.Kind]string + golangTypes []reflect.Type + types map[reflect.Kind]string - // throwaway, used when converting + // throwaway, used when converting alreadyConverted map[reflect.Type]bool } @@ -101,7 +103,7 @@ func (this *TypeScriptify) Convert(customCode map[string]string) (string, error) if err != nil { return "", err } - result += "\n" + strings.Trim(typeScriptCode, " "+this.Indent+"\r\n") + result += "\n" + strings.Trim(typeScriptCode, " " + this.Indent + "\r\n") } return result, nil } @@ -205,6 +207,11 @@ func (this TypeScriptify) ConvertToFile(fileName string) error { return nil } +func IsExported(name string) bool { + ch, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(ch) +} + func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[string]string, customName ...string) (string, error) { if typeOf == TimeType { return "", nil @@ -234,6 +241,9 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin fields := deepFields(typeOf) for _, field := range fields { + if !IsExported(field.Name) { + continue // skip unexported field + } jsonTag := field.Tag.Get("json") jsonFieldName := "" fieldType := field.Type @@ -255,7 +265,28 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin fmt.Println("jsonFieldName", jsonFieldName) if len(jsonFieldName) > 0 && jsonFieldName != "-" { var err error - if fieldType.Kind() == reflect.Struct { + if fieldType.Kind() == reflect.Interface { + // empty interface + builder.AddStructField(jsonFieldName, "any") + } else if fieldType.Kind() == reflect.Map { + // map[string]interface{} + fmt.Println(fieldType.Key()) + keyType := "string" + if kt, ok := this.types[fieldType.Key().Kind()]; ok { + keyType = kt + } + valType := "any" + mapValueType := fieldType.Elem() + if mapValueType.Kind() == reflect.Ptr { + mapValueType = mapValueType.Elem() + } + if mapValueType.Kind() == reflect.Struct { + valType = mapValueType.Name() + } else if vt, ok := this.types[mapValueType.Kind()]; ok { + valType = vt + } + builder.AddStructField(jsonFieldName, "{[key: " + keyType + "]: " + valType + "}") + } else if fieldType.Kind() == reflect.Struct { // Struct: fieldTypeName := fieldType.Name() if fieldTypeName == "" { @@ -353,7 +384,7 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string) { this.fields += fmt.Sprintf("%s%s: %s;\n", this.indent, fieldName, fieldType) createCall := fieldType + ".createFrom" - if fieldType == "Date" || fieldType == "string" { + if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... } this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null;\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) From 5bbe59fe3229bf6a1b4899b0f835f60dae25243d Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Wed, 18 May 2016 23:15:55 +0800 Subject: [PATCH 09/15] resolve map value type --- typescriptify/typescriptify.go | 39 ++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index ec8d7ce..5963f95 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -19,6 +19,7 @@ type TypeScriptify struct { Suffix string Indent string CreateFromMethod bool + UseInterface bool BackupExtension string // If empty no backup golangTypes []reflect.Type @@ -233,7 +234,11 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin entityName = fmt.Sprintf("%s%s%s", this.Prefix, this.Suffix, customName[0]) } - result := fmt.Sprintf("export class %s {\n", entityName) + typeKind := "class" + if this.UseInterface { + typeKind = "interface" + } + result := fmt.Sprintf("export %s %s {\n", typeKind, entityName) builder := typeScriptClassBuilder{ types: this.types, indent: this.Indent, @@ -247,7 +252,8 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin jsonTag := field.Tag.Get("json") jsonFieldName := "" fieldType := field.Type - if fieldType.Kind() == reflect.Ptr { + isPtr := fieldType.Kind() == reflect.Ptr + if isPtr { fieldType = field.Type.Elem() } if len(jsonTag) > 0 { @@ -282,10 +288,17 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } if mapValueType.Kind() == reflect.Struct { valType = mapValueType.Name() + typeScriptChunk, err := this.convertType(mapValueType, customCode) + if err != nil { + return "", err + } + if typeScriptChunk != "" { + result = typeScriptChunk + "\n" + result + } } else if vt, ok := this.types[mapValueType.Kind()]; ok { valType = vt } - builder.AddStructField(jsonFieldName, "{[key: " + keyType + "]: " + valType + "}") + builder.AddStructField(jsonFieldName, "{[key: " + keyType + "]: " + valType + "}", true) } else if fieldType.Kind() == reflect.Struct { // Struct: fieldTypeName := fieldType.Name() @@ -301,7 +314,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin //fieldTypeName = "Date" fieldTypeName = "string" } - builder.AddStructField(jsonFieldName, fieldTypeName) + builder.AddStructField(jsonFieldName, fieldTypeName, isPtr) } else if fieldType.Kind() == reflect.Slice { // Slice: elemType := fieldType.Elem() @@ -323,7 +336,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } } else { // Simple field: - err = builder.AddSimpleField(jsonFieldName, fieldType.Name(), fieldType.Kind()) + err = builder.AddSimpleField(jsonFieldName, fieldType.Name(), fieldType.Kind(), isPtr) } if err != nil { return "", err @@ -370,10 +383,14 @@ func (this *typeScriptClassBuilder) AddSimpleArrayField(fieldName, fieldType str return errors.New(fmt.Sprintf("Cannot find type for %s (%s/%s)", kind.String(), fieldName, fieldType)) } -func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, kind reflect.Kind) error { +func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, kind reflect.Kind, isPtr... bool) error { + optional := "" + if len(isPtr) > 0 && isPtr[0] { + optional = "?" + } if typeScriptType, ok := this.types[kind]; ok { if len(fieldName) > 0 { - this.fields += fmt.Sprintf("%s%s: %s;\n", this.indent, fieldName, typeScriptType) + this.fields += fmt.Sprintf("%s%s%s: %s;\n", this.indent, fieldName, optional, typeScriptType) this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"];\n", this.indent, this.indent, fieldName, fieldName) return nil } @@ -381,8 +398,12 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, return errors.New("Cannot find type for " + fieldType) } -func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string) { - this.fields += fmt.Sprintf("%s%s: %s;\n", this.indent, fieldName, fieldType) +func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, isPtr... bool) { + optional := "" + if len(isPtr) > 0 && isPtr[0] { + optional = "?" + } + this.fields += fmt.Sprintf("%s%s%s: %s;\n", this.indent, fieldName, optional, fieldType) createCall := fieldType + ".createFrom" if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... From 4dcb518545777c4662cb3641a736efea99aea3c8 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Sat, 11 Jun 2016 15:42:14 +0800 Subject: [PATCH 10/15] add support for interface{} and anonymous struct array --- typescriptify/typescriptify.go | 41 +++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 5963f95..70d7329 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -22,10 +22,10 @@ type TypeScriptify struct { UseInterface bool BackupExtension string // If empty no backup - golangTypes []reflect.Type - types map[reflect.Kind]string + golangTypes []reflect.Type + types map[reflect.Kind]string - // throwaway, used when converting + // throwaway, used when converting alreadyConverted map[reflect.Type]bool } @@ -53,6 +53,8 @@ func New() *TypeScriptify { types[reflect.String] = "string" + types[reflect.Interface] = "any" + result.types = types result.Indent = " " @@ -104,7 +106,7 @@ func (this *TypeScriptify) Convert(customCode map[string]string) (string, error) if err != nil { return "", err } - result += "\n" + strings.Trim(typeScriptCode, " " + this.Indent + "\r\n") + result += "\n" + strings.Trim(typeScriptCode, " "+this.Indent+"\r\n") } return result, nil } @@ -245,6 +247,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } fields := deepFields(typeOf) + fmt.Println(typeOf.Name(), typeOf.Kind(), entityName, "fields:", fields) for _, field := range fields { if !IsExported(field.Name) { continue // skip unexported field @@ -269,11 +272,14 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } } fmt.Println("jsonFieldName", jsonFieldName) + if len(jsonFieldName) > 0 && jsonFieldName != "-" { var err error + if fieldType.Kind() == reflect.Interface { // empty interface builder.AddStructField(jsonFieldName, "any") + } else if fieldType.Kind() == reflect.Map { // map[string]interface{} fmt.Println(fieldType.Key()) @@ -298,12 +304,13 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } else if vt, ok := this.types[mapValueType.Kind()]; ok { valType = vt } - builder.AddStructField(jsonFieldName, "{[key: " + keyType + "]: " + valType + "}", true) + builder.AddStructField(jsonFieldName, "{[key: "+keyType+"]: "+valType+"}", true) + } else if fieldType.Kind() == reflect.Struct { // Struct: fieldTypeName := fieldType.Name() if fieldTypeName == "" { - fieldTypeName = "__" + entityName + "_" + jsonFieldName + fieldTypeName = "__" + entityName + "_" + jsonFieldName // inline struct declaration } typeScriptChunk, err := this.convertType(fieldType, customCode, fieldTypeName) if err != nil { @@ -315,6 +322,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin fieldTypeName = "string" } builder.AddStructField(jsonFieldName, fieldTypeName, isPtr) + } else if fieldType.Kind() == reflect.Slice { // Slice: elemType := fieldType.Elem() @@ -322,18 +330,31 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin fmt.Println("Ptr type", fieldType) elemType = elemType.Elem() } + if elemType.Kind() == reflect.Struct { // Slice of structs: - typeScriptChunk, err := this.convertType(elemType, customCode) + elemTypeName := elemType.Name() + if elemTypeName == "" { + elemTypeName = "__" + entityName + "_" + jsonFieldName // inline struct declaration + } + typeScriptChunk, err := this.convertType(elemType, customCode, elemTypeName) if err != nil { return "", err } result = typeScriptChunk + "\n" + result - builder.AddArrayOfStructsField(jsonFieldName, elemType.Name()) + if elemType.Name() != "" { + builder.AddArrayOfStructsField(jsonFieldName, elemType.Name()) + } else { + builder.AddArrayOfStructsField(jsonFieldName, elemTypeName) + } + + } else if elemType.Kind() == reflect.Interface { + err = builder.AddSimpleArrayField(jsonFieldName, elemType.Name(), elemType.Kind()) } else { // Slice of simple fields: err = builder.AddSimpleArrayField(jsonFieldName, elemType.Name(), elemType.Kind()) } + } else { // Simple field: err = builder.AddSimpleField(jsonFieldName, fieldType.Name(), fieldType.Kind(), isPtr) @@ -383,7 +404,7 @@ func (this *typeScriptClassBuilder) AddSimpleArrayField(fieldName, fieldType str return errors.New(fmt.Sprintf("Cannot find type for %s (%s/%s)", kind.String(), fieldName, fieldType)) } -func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, kind reflect.Kind, isPtr... bool) error { +func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, kind reflect.Kind, isPtr ...bool) error { optional := "" if len(isPtr) > 0 && isPtr[0] { optional = "?" @@ -398,7 +419,7 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, return errors.New("Cannot find type for " + fieldType) } -func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, isPtr... bool) { +func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, isPtr ...bool) { optional := "" if len(isPtr) > 0 && isPtr[0] { optional = "?" From 37257abe91e7518ced79bdadf145ef7fb2a2a8a1 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Mon, 27 Feb 2017 15:52:56 +0800 Subject: [PATCH 11/15] add CreateFromMethod and AllOptional --- typescriptify/typescriptify.go | 81 +++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 70d7329..5177829 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -15,18 +15,20 @@ import ( var TimeType = reflect.TypeOf(time.Now()) type TypeScriptify struct { - Prefix string - Suffix string - Indent string - CreateFromMethod bool - UseInterface bool - BackupExtension string // If empty no backup + Prefix string + Suffix string + Indent string + CreateConstructor bool + UseInterface bool + BackupExtension string // If empty no backup golangTypes []reflect.Type types map[reflect.Kind]string // throwaway, used when converting alreadyConverted map[reflect.Type]bool + + AllOptional bool } func New() *TypeScriptify { @@ -58,7 +60,7 @@ func New() *TypeScriptify { result.types = types result.Indent = " " - result.CreateFromMethod = true + result.CreateConstructor = true return result } @@ -242,8 +244,9 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } result := fmt.Sprintf("export %s %s {\n", typeKind, entityName) builder := typeScriptClassBuilder{ - types: this.types, - indent: this.Indent, + types: this.types, + indent: this.Indent, + AllOptional: this.AllOptional, } fields := deepFields(typeOf) @@ -366,14 +369,22 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } result += builder.fields - if this.CreateFromMethod { - result += fmt.Sprintf("\n%sstatic createFrom(source: any) {\n", this.Indent) - result += fmt.Sprintf("%s%svar result = new %s();\n", this.Indent, this.Indent, entityName) + if this.CreateConstructor { + result += fmt.Sprintf("\n%sconstructor(init?: %s) {\n", this.Indent, entityName) + // result += fmt.Sprintf("%s%svar result = new %s()\n", this.Indent, this.Indent, entityName) result += builder.createFromMethodBody - result += fmt.Sprintf("%s%sreturn result;\n", this.Indent, this.Indent) + // result += fmt.Sprintf("%s%sreturn result\n", this.Indent, this.Indent) result += fmt.Sprintf("%s}\n\n", this.Indent) } + // if this.CreateConstructor { + // result += fmt.Sprintf("\n%sstatic createFrom(source: any) {\n", this.Indent) + // result += fmt.Sprintf("%s%svar result = new %s()\n", this.Indent, this.Indent, entityName) + // result += builder.createFromMethodBody + // result += fmt.Sprintf("%s%sreturn result\n", this.Indent, this.Indent) + // result += fmt.Sprintf("%s}\n\n", this.Indent) + // } + if customCode != nil { code := customCode[entityName] if code != "" { @@ -391,13 +402,16 @@ type typeScriptClassBuilder struct { indent string fields string createFromMethodBody string + + AllOptional bool } func (this *typeScriptClassBuilder) AddSimpleArrayField(fieldName, fieldType string, kind reflect.Kind) error { if typeScriptType, ok := this.types[kind]; ok { if len(fieldName) > 0 { - this.fields += fmt.Sprintf("%s%s: %s[];\n", this.indent, fieldName, typeScriptType) - this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"];\n", this.indent, this.indent, fieldName, fieldName) + this.fields += fmt.Sprintf("%s%s: %s[]\n", this.indent, fieldName, typeScriptType) + // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"]\n", this.indent, this.indent, fieldName, fieldName) + this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) return nil } } @@ -406,13 +420,14 @@ func (this *typeScriptClassBuilder) AddSimpleArrayField(fieldName, fieldType str func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, kind reflect.Kind, isPtr ...bool) error { optional := "" - if len(isPtr) > 0 && isPtr[0] { + if this.AllOptional || len(isPtr) > 0 && isPtr[0] { optional = "?" } if typeScriptType, ok := this.types[kind]; ok { if len(fieldName) > 0 { - this.fields += fmt.Sprintf("%s%s%s: %s;\n", this.indent, fieldName, optional, typeScriptType) - this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"];\n", this.indent, this.indent, fieldName, fieldName) + this.fields += fmt.Sprintf("%s%s%s: %s\n", this.indent, fieldName, optional, typeScriptType) + // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"]\n", this.indent, this.indent, fieldName, fieldName) + this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) return nil } } @@ -421,22 +436,26 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, isPtr ...bool) { optional := "" - if len(isPtr) > 0 && isPtr[0] { + if this.AllOptional || len(isPtr) > 0 && isPtr[0] { optional = "?" } - this.fields += fmt.Sprintf("%s%s%s: %s;\n", this.indent, fieldName, optional, fieldType) - createCall := fieldType + ".createFrom" - if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { - createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... - } - this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null;\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) + this.fields += fmt.Sprintf("%s%s%s: %s\n", this.indent, fieldName, optional, fieldType) + // createCall := fieldType + ".createFrom" + // if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { + // createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... + // } + // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) + + this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) } func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType string) { - this.fields += fmt.Sprintf("%s%s: %s[];\n", this.indent, fieldName, fieldType) - createCall := fieldType + ".createFrom" - if fieldType == "Date" || fieldType == "string" { - createCall = "" - } - this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) + this.fields += fmt.Sprintf("%s%s: %s[]\n", this.indent, fieldName, fieldType) + // createCall := fieldType + ".createFrom" + // if fieldType == "Date" || fieldType == "string" { + // createCall = "" + // } + // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) + + this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) } From ace045413b4964594b6dfe2108f01988f9871edf Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Mon, 27 Feb 2017 17:01:56 +0800 Subject: [PATCH 12/15] fix constructor --- typescriptify/typescriptify.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 5177829..328af1f 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -371,6 +371,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin result += builder.fields if this.CreateConstructor { result += fmt.Sprintf("\n%sconstructor(init?: %s) {\n", this.Indent, entityName) + result += fmt.Sprintf("%s%sif (!init) return\n", this.Indent, this.Indent) // result += fmt.Sprintf("%s%svar result = new %s()\n", this.Indent, this.Indent, entityName) result += builder.createFromMethodBody // result += fmt.Sprintf("%s%sreturn result\n", this.Indent, this.Indent) @@ -411,7 +412,7 @@ func (this *typeScriptClassBuilder) AddSimpleArrayField(fieldName, fieldType str if len(fieldName) > 0 { this.fields += fmt.Sprintf("%s%s: %s[]\n", this.indent, fieldName, typeScriptType) // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"]\n", this.indent, this.indent, fieldName, fieldName) - this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) + this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) return nil } } @@ -427,7 +428,7 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, if len(fieldName) > 0 { this.fields += fmt.Sprintf("%s%s%s: %s\n", this.indent, fieldName, optional, typeScriptType) // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"]\n", this.indent, this.indent, fieldName, fieldName) - this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) + this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) return nil } } @@ -446,7 +447,7 @@ func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, // } // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) - this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) + this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) } func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType string) { @@ -457,5 +458,5 @@ func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType // } // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) - this.createFromMethodBody += fmt.Sprintf("%s%sthis.%s = init.%s ? init.%s : null\n", this.indent, this.indent, fieldName, fieldName, fieldName) + this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) } From ebfca0e71b6f5358eeabcebf42320921aca05565 Mon Sep 17 00:00:00 2001 From: Adrian Huang Date: Thu, 9 Mar 2017 19:48:02 +0800 Subject: [PATCH 13/15] add create empty object static function and AllModelTypes map --- typescriptify/typescriptify.go | 54 +++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index 328af1f..e5f6289 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -19,11 +19,13 @@ type TypeScriptify struct { Suffix string Indent string CreateConstructor bool + CreateEmptyObject bool UseInterface bool BackupExtension string // If empty no backup golangTypes []reflect.Type types map[reflect.Kind]string + structTypes map[string]reflect.Type // throwaway, used when converting alreadyConverted map[reflect.Type]bool @@ -58,6 +60,7 @@ func New() *TypeScriptify { types[reflect.Interface] = "any" result.types = types + result.structTypes = make(map[string]reflect.Type) result.Indent = " " result.CreateConstructor = true @@ -110,6 +113,14 @@ func (this *TypeScriptify) Convert(customCode map[string]string) (string, error) } result += "\n" + strings.Trim(typeScriptCode, " "+this.Indent+"\r\n") } + + structItems := "" + for tsStructTypeName, _ := range this.structTypes { + structItems += fmt.Sprintf("\"%s\":%s,\n", tsStructTypeName, tsStructTypeName) + } + + result += fmt.Sprintf("\nexport let AllModelTypes = {\n%s}\n", structItems) + return result, nil } @@ -242,9 +253,11 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin if this.UseInterface { typeKind = "interface" } + this.structTypes[entityName] = typeOf result := fmt.Sprintf("export %s %s {\n", typeKind, entityName) builder := typeScriptClassBuilder{ types: this.types, + structTypes: this.structTypes, indent: this.Indent, AllOptional: this.AllOptional, } @@ -323,6 +336,8 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin if fieldType == TimeType { //fieldTypeName = "Date" fieldTypeName = "string" + } else { + this.structTypes[fieldTypeName] = fieldType } builder.AddStructField(jsonFieldName, fieldTypeName, isPtr) @@ -345,6 +360,7 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin return "", err } result = typeScriptChunk + "\n" + result + this.structTypes[elemTypeName] = elemType if elemType.Name() != "" { builder.AddArrayOfStructsField(jsonFieldName, elemType.Name()) } else { @@ -378,6 +394,14 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin result += fmt.Sprintf("%s}\n\n", this.Indent) } + if this.CreateEmptyObject { + result += fmt.Sprintf("\n%sstatic emptyObject(): %s {\n", this.Indent, entityName) + result += fmt.Sprintf("%s%svar result = new %s()\n", this.Indent, this.Indent, entityName) + result += builder.createEmptyObjectBody + result += fmt.Sprintf("%s%sreturn result\n", this.Indent, this.Indent) + result += fmt.Sprintf("%s}\n\n", this.Indent) + } + // if this.CreateConstructor { // result += fmt.Sprintf("\n%sstatic createFrom(source: any) {\n", this.Indent) // result += fmt.Sprintf("%s%svar result = new %s()\n", this.Indent, this.Indent, entityName) @@ -399,10 +423,12 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin } type typeScriptClassBuilder struct { - types map[reflect.Kind]string - indent string - fields string - createFromMethodBody string + types map[reflect.Kind]string + structTypes map[string]reflect.Type + indent string + fields string + createFromMethodBody string + createEmptyObjectBody string AllOptional bool } @@ -412,6 +438,8 @@ func (this *typeScriptClassBuilder) AddSimpleArrayField(fieldName, fieldType str if len(fieldName) > 0 { this.fields += fmt.Sprintf("%s%s: %s[]\n", this.indent, fieldName, typeScriptType) // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"]\n", this.indent, this.indent, fieldName, fieldName) + fieldEmptyValue := "[]" + this.createEmptyObjectBody += fmt.Sprintf("%s%sresult.%s = %s\n", this.indent, this.indent, fieldName, fieldEmptyValue) this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) return nil } @@ -428,6 +456,17 @@ func (this *typeScriptClassBuilder) AddSimpleField(fieldName, fieldType string, if len(fieldName) > 0 { this.fields += fmt.Sprintf("%s%s%s: %s\n", this.indent, fieldName, optional, typeScriptType) // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"]\n", this.indent, this.indent, fieldName, fieldName) + fieldEmptyValue := "" + if typeScriptType == "string" { + fieldEmptyValue = "\"\"" + } else if typeScriptType == "number" { + fieldEmptyValue = "0" + } else if typeScriptType == "boolean" { + fieldEmptyValue = "false" + } else if typeScriptType == "any" { + fieldEmptyValue = "null" + } + this.createEmptyObjectBody += fmt.Sprintf("%s%sresult.%s = %s\n", this.indent, this.indent, fieldName, fieldEmptyValue) this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) return nil } @@ -446,6 +485,11 @@ func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, // createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically... // } // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) + fieldEmptyValue := fmt.Sprintf("%s.emptyObject()", fieldType) + if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { + fieldEmptyValue = "\"\"" // for Date, keep the string..., because JS won't deserialize to Date object automatically... + } + this.createEmptyObjectBody += fmt.Sprintf("%s%sresult.%s = %s\n", this.indent, this.indent, fieldName, fieldEmptyValue) this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) } @@ -457,6 +501,8 @@ func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType // createCall = "" // } // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? source[\"%s\"].map(function(element) { return %s(element); }) : null;\n", this.indent, this.indent, fieldName, fieldName, fieldName, createCall) + fieldEmptyValue := "[]" + this.createEmptyObjectBody += fmt.Sprintf("%s%sresult.%s = %s\n", this.indent, this.indent, fieldName, fieldEmptyValue) this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) } From e1bc402de5e34c146c98ceecce8860ad2ca2aa15 Mon Sep 17 00:00:00 2001 From: Florian Kinder Date: Mon, 4 Dec 2017 09:53:54 +0100 Subject: [PATCH 14/15] Added method to register custom date & fixes --- typescriptify/typescriptify.go | 44 ++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index e5f6289..bd9865c 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -12,8 +12,6 @@ import ( "unicode/utf8" ) -var TimeType = reflect.TypeOf(time.Now()) - type TypeScriptify struct { Prefix string Suffix string @@ -26,6 +24,7 @@ type TypeScriptify struct { golangTypes []reflect.Type types map[reflect.Kind]string structTypes map[string]reflect.Type + dateTypes []reflect.Type // throwaway, used when converting alreadyConverted map[reflect.Type]bool @@ -59,6 +58,10 @@ func New() *TypeScriptify { types[reflect.Interface] = "any" + result.dateTypes = []reflect.Type{ + reflect.TypeOf(time.Now()), + } + result.types = types result.structTypes = make(map[string]reflect.Type) @@ -102,6 +105,10 @@ func (this *TypeScriptify) AddType(typeOf reflect.Type) { this.golangTypes = append(this.golangTypes, typeOf) } +func (this *TypeScriptify) RegisterDateType(typeOf reflect.Type) { + this.dateTypes = append(this.dateTypes, typeOf) +} + func (this *TypeScriptify) Convert(customCode map[string]string) (string, error) { this.alreadyConverted = make(map[reflect.Type]bool) @@ -229,8 +236,10 @@ func IsExported(name string) bool { } func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[string]string, customName ...string) (string, error) { - if typeOf == TimeType { - return "", nil + for _, v := range this.dateTypes { + if v == typeOf { + return "", nil + } } isAnonymousStruct := len(customName) > 0 && customName[0] != typeOf.Name() @@ -333,10 +342,17 @@ func (this *TypeScriptify) convertType(typeOf reflect.Type, customCode map[strin return "", err } result = typeScriptChunk + "\n" + result - if fieldType == TimeType { - //fieldTypeName = "Date" - fieldTypeName = "string" - } else { + + isDateField := false + for _, v := range this.dateTypes { + if v != fieldType { + continue + } + + isDateField = true + fieldTypeName = "Date" + } + if !isDateField { this.structTypes[fieldTypeName] = fieldType } builder.AddStructField(jsonFieldName, fieldTypeName, isPtr) @@ -486,12 +502,20 @@ func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, // } // this.createFromMethodBody += fmt.Sprintf("%s%sresult.%s = source[\"%s\"] ? %s(source[\"%s\"]) : null\n", this.indent, this.indent, fieldName, fieldName, createCall, fieldName) fieldEmptyValue := fmt.Sprintf("%s.emptyObject()", fieldType) - if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { + if fieldType == "string" || fieldType == "any" { fieldEmptyValue = "\"\"" // for Date, keep the string..., because JS won't deserialize to Date object automatically... } + if strings.HasPrefix(fieldType, "{") { + fieldEmptyValue = "null" + } + if fieldType == "Date" { + fieldEmptyValue = "null" + this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = new Date(init.%s as any)\n", this.indent, this.indent, fieldName, fieldName, fieldName) + } else { + this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) + } this.createEmptyObjectBody += fmt.Sprintf("%s%sresult.%s = %s\n", this.indent, this.indent, fieldName, fieldEmptyValue) - this.createFromMethodBody += fmt.Sprintf("%s%sif (init.%s) this.%s = init.%s\n", this.indent, this.indent, fieldName, fieldName, fieldName) } func (this *typeScriptClassBuilder) AddArrayOfStructsField(fieldName, fieldType string) { From 5d1a6662797344a311fe5bbc64f827bfde438944 Mon Sep 17 00:00:00 2001 From: Florian Kinder Date: Fri, 5 Jan 2018 11:35:15 +0100 Subject: [PATCH 15/15] Added missing semi colon after struct fields --- typescriptify/typescriptify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescriptify/typescriptify.go b/typescriptify/typescriptify.go index bd9865c..ffbe809 100644 --- a/typescriptify/typescriptify.go +++ b/typescriptify/typescriptify.go @@ -495,7 +495,7 @@ func (this *typeScriptClassBuilder) AddStructField(fieldName, fieldType string, if this.AllOptional || len(isPtr) > 0 && isPtr[0] { optional = "?" } - this.fields += fmt.Sprintf("%s%s%s: %s\n", this.indent, fieldName, optional, fieldType) + this.fields += fmt.Sprintf("%s%s%s: %s;\n", this.indent, fieldName, optional, fieldType) // createCall := fieldType + ".createFrom" // if fieldType == "Date" || fieldType == "string" || fieldType == "any" || strings.HasPrefix(fieldType, "{") { // createCall = "" // for Date, keep the string..., because JS won't deserialize to Date object automatically...