-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
const tab = "\t" | ||
|
||
var ( | ||
pkgName string | ||
fileFormat string | ||
directory string | ||
) | ||
|
||
func fetch(u string, v interface{}) error { | ||
r, err := http.Get(u) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer r.Body.Close() | ||
return json.NewDecoder(r.Body).Decode(v) | ||
} | ||
|
||
func must(err error) { | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func init() { | ||
flag.StringVar(&pkgName, "pkg", "xivapi", "Define the root package name") | ||
flag.StringVar(&fileFormat, "format", "type_%v_generated.go", "File template to use for filenames") | ||
flag.StringVar(&directory, "d", ".", "directory to generate the files in") | ||
} | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
var types []string | ||
|
||
fmt.Println("fetching content types...") | ||
must(fetch("https://xivapi.com/content", &types)) | ||
fmt.Printf("generating structs for %d types...\n", len(types)) | ||
|
||
for _, t := range types { | ||
strct := genStruct(t) | ||
|
||
f := filepath.Join(directory, fmt.Sprintf(fileFormat, t)) | ||
os.Remove(f) | ||
h, err := os.Create(f) | ||
must(err) | ||
|
||
fmt.Fprintf(h, `// Code generated by generate_structs - DO NOT EDIT. | ||
package %v | ||
type %v`, pkgName, strct) | ||
h.Close() | ||
} | ||
} | ||
|
||
type schema struct { | ||
Columns []string | ||
ContentSchema map[string]json.RawMessage | ||
} | ||
|
||
func genStruct(t string) string { | ||
schema := new(schema) | ||
fmt.Printf("- fetching %v...\n", t) | ||
must(fetch(fmt.Sprintf("https://xivapi.com/%v?schema=1", t), schema)) | ||
fmt.Printf(" %d columns found...\n", len(schema.Columns)) | ||
|
||
return parseSchema(t, schema.ContentSchema, 1) | ||
} | ||
|
||
func parseSchema(t string, schema map[string]json.RawMessage, depth int) string { | ||
source := fmt.Sprintf("%v%v struct {\n", strings.Repeat(tab, depth-1), t) | ||
indent := strings.Repeat(tab, depth) | ||
|
||
for name, def := range schema { | ||
typ := "" | ||
err := json.Unmarshal(def, &typ) | ||
if err != nil { | ||
subSchema := make(map[string]json.RawMessage) | ||
err := errors.Wrap(json.Unmarshal(def, &subSchema), name) | ||
if err != nil { | ||
fmt.Println("!!", err, "!!") | ||
continue | ||
} | ||
source += parseSchema(name, subSchema, depth+1) | ||
} else { | ||
source += fmt.Sprintf("%v%v %v `json:\"%v,omitempty\"`\n", indent, name, goType(typ), name) | ||
} | ||
} | ||
return source + strings.Repeat(tab, depth-1) + "}\n" | ||
} | ||
|
||
func goType(def string) string { | ||
trimmed := strings.TrimSpace(def) | ||
switch trimmed { | ||
case "array": | ||
return "[]interface{}" | ||
case "[?]": | ||
return "interface{}" | ||
case "boolean": | ||
return "bool" | ||
case "int", "string": | ||
return trimmed | ||
default: | ||
fmt.Printf("!! unkown type: `%v` !!\n", trimmed) | ||
return "interface{}" | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.