{"id":13616322,"url":"https://github.com/antlabs/tostruct","last_synced_at":"2026-01-30T16:22:43.659Z","repository":{"id":65417089,"uuid":"590347163","full_name":"antlabs/tostruct","owner":"antlabs","description":"Generate struct definition according to json/yaml/query string/http header string @^^@ 根据json/yaml/query string/http header字符串生成struct[从零实现]","archived":false,"fork":false,"pushed_at":"2023-03-13T15:42:40.000Z","size":59,"stargazers_count":16,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-02T20:48:08.098Z","etag":null,"topics":["2","header","json","query","srtring","struct","to","url","yaml"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antlabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-18T07:48:33.000Z","updated_at":"2024-03-12T08:03:02.000Z","dependencies_parsed_at":"2024-06-21T15:21:30.981Z","dependency_job_id":"2f43a6dc-4d9d-4881-b4a3-2a181b4bb335","html_url":"https://github.com/antlabs/tostruct","commit_stats":{"total_commits":38,"total_committers":1,"mean_commits":38.0,"dds":0.0,"last_synced_commit":"a77c5a61a6c7ecce0325bbf5cb4e45f767271d1e"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antlabs%2Ftostruct","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antlabs%2Ftostruct/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antlabs%2Ftostruct/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antlabs%2Ftostruct/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antlabs","download_url":"https://codeload.github.com/antlabs/tostruct/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223611916,"owners_count":17173533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2","header","json","query","srtring","struct","to","url","yaml"],"created_at":"2024-08-01T20:01:26.909Z","updated_at":"2026-01-30T16:22:43.614Z","avatar_url":"https://github.com/antlabs.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# tostruct\n[![Go](https://github.com/antlabs/tostruct/workflows/Go/badge.svg)](https://github.com/antlabs/tostruct/actions)\n[![codecov](https://codecov.io/gh/antlabs/tostruct/branch/master/graph/badge.svg)](https://codecov.io/gh/antlabs/tostruct)\n\njson/yaml/http header/query string 转成struct定义，免去手写struct的烦恼.    \n## 零、特性\n* json 生成golang struct\n* yaml 生成golang struct\n* http.Header 生成golang struct\n* http url 生成golang struct\n* json/yaml 生成protobuf message定义\n\n## 一、json/yaml/http header/query string 生成结构体\n### 1.1 json字符串生成结构体\n```go\nimport (\n    \"github.com/antlabs/tostruct/json\"\n    \"github.com/antlabs/tostruct/option\"\n)\n\nfunc main() {\n\tvar str = `{\n\t\"action\": \"Deactivate user\",\n\t\"entities\": [\n\t\t{\n\t\t\"uuid\": \"4759aa70-XXXX-XXXX-925f-6fa0510823ba\",\n\t\t\"type\": \"user\",\n\t\t\"created\": 1542595573399,\n\t\t\"modified\": 1542597578147,\n\t\t\"username\": \"user1\",\n\t\t\"activated\": false,\n\t\t\"nickname\": \"user\"\n\t\t}],\n\t\t\"timestamp\": 1542602157258,\n\t\t\"duration\": 12\n\t}`\n\n\t// 父子结构合在一起\n\tall, _ := json.Marshal([]byte(str), option.WithStructName(\"reqName\"))\n\tfmt.Println(string(all))\n\t/*\n\ttype reqName struct {\n\t\tAction   string `json:\"action\"`\n\t\tDuration int    `json:\"duration\"`\n\t\tEntities []struct {\n\t\t\tActivated bool   `json:\"activated\"`\n\t\t\tCreated   int    `json:\"created\"`\n\t\t\tModified  int    `json:\"modified\"`\n\t\t\tNickname  string `json:\"nickname\"`\n\t\t\tType      string `json:\"type\"`\n\t\t\tUsername  string `json:\"username\"`\n\t\t\tUUID      string `json:\"uuid\"`\n\t\t} `json:\"entities\"`\n\t\tTimestamp int `json:\"timestamp\"`\n\t}\n\t*/\n\n\t// 子结构拆分\n\tall, _ := json.Marshal([]byte(str), option.WithStructName(\"reqName\"), option.WithNotInline())\n\tfmt.Println(string(all))\n\t/*\n\ttype reqName struct {\n\t\tAction    string     `json:\"action\"`\n\t\tDuration  int        `json:\"duration\"`\n\t\tEntities  []Entities `json:\"entities\"`\n\t\tTimestamp int        `json:\"timestamp\"`\n\t}\n\n\ttype Entities struct {\n\t\tActivated bool   `json:\"activated\"`\n\t\tCreated   int    `json:\"created\"`\n\t\tModified  int    `json:\"modified\"`\n\t\tNickname  string `json:\"nickname\"`\n\t\tType      string `json:\"type\"`\n\t\tUsername  string `json:\"username\"`\n\t\tUUID      string `json:\"uuid\"`\n\t}\n\t*/\n}\n```\n\n### 1.2 http header生成结构体\n```go\nimport (\n    \"github.com/antlabs/tostruct/header\"\n    \"github.com/antlabs/tostruct/option\"\n\t\"net/http\"\n)\n\nfunc main() {\n\th := http.header{\n\t\t\"bool\": []string{\"true\"},\n\t\t\"int\" : []string{\"1\"},\n\t\t\"string\" : []string{\"hello\"},\n\t\t\"float64\" : []string{\"3.14\"},\n\t}\n\tres, err := header.Marshal(h, option.WithStructName(\"test\"), option.WithTagName(\"header\"))\n\tif err != nil {\n\t\tfmt.Println(err.Error())\n\t\treturn\n\t}\n\n\tfmt.Println(string(res))\n\t/*\ntype test struct {\n\tBool    bool    `header:\"bool\"`\n\tFloat64 float64 `header:\"float64\"`\n\tInt     int     `header:\"int\"`\n\tString  string  `header:\"string\"`\n}\n\t*/\n}\n```\n### 1.3、查询字符串生成结构体\n```go\nimport (\n    \"github.com/antlabs/tostruct/url\"\n    \"github.com/antlabs/tostruct/option\"\n)\n\nfunc main() {\n\turl := \"http://127.0.0.1:8080?int=1\u0026float64=1.1\u0026bool=true\u0026string=hello\"\n\tres, err := header.Marshal(h, option.WithStructName(\"test\"), option.WithTagName(\"form\"))\n\tif err != nil {\n\t\tfmt.Println(err.Error())\n\t\treturn\n\t}\n\tfmt.Println(string(res))\n\t/*\ntype test struct {\n\tBool    bool    `form:\"bool\"`\n\tFloat64 float64 `form:\"float64\"`\n\tInt     int     `form:\"int\"`\n\tString  string  `form:\"string\"`\n}\n\t*/\n}\n\n```\n\n### 1.4 yaml生成结构体\n```go\nimport (\n    \"github.com/antlabs/tostruct/url\"\n    \"github.com/antlabs/tostruct/option\"\n\t\"github.com/antlabs/tostruct/yaml\"\n)\n\nfunc main() {\n\tstr := `\na: 1\nb: 3.14\nc: hello\nd:\n  - aa\n  - bb\ne:\n  - a: 1\n    b: 3.14\n    c: hello\nf:\n  first: 1\n  second: 3.14\n`\n\n\tall, err := Marshal([]byte(str), option.WithStructName(\"reqName\"))\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(all)\n\t/*\ntype reqName struct {\n\tA int      `yaml:\"a\"`\n\tB float64  `yaml:\"b\"`\n\tC string   `yaml:\"c\"`\n\tD []string `yaml:\"d\"`\n\tE []struct {\n\t\tA int     `yaml:\"a\"`\n\t\tB float64 `yaml:\"b\"`\n\t\tC string  `yaml:\"c\"`\n\t} `yaml:\"e\"`\n\tF struct {\n\t\tFirst  int     `yaml:\"first\"`\n\t\tSecond float64 `yaml:\"second\"`\n\t} `yaml:\"f\"`\n}\n\n\t*/\n\n\tall, err := Marshal([]byte(str), option.WithStructName(\"reqName\"), option.WithNotInline())\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(all)\n/*\ntype reqName struct {\n\tA int      `yaml:\"a\"`\n\tB float64  `yaml:\"b\"`\n\tC string   `yaml:\"c\"`\n\tD []string `yaml:\"d\"`\n\tE []E      `yaml:\"e\"`\n\tF F        `yaml:\"f\"`\n}\n\ntype E struct {\n\tA int     `yaml:\"a\"`\n\tB float64 `yaml:\"b\"`\n\tC string  `yaml:\"c\"`\n}\n\ntype F struct {\n\tFirst  int     `yaml:\"first\"`\n\tSecond float64 `yaml:\"second\"`\n}\n*/\n}\n```\n### 1.5 json/yaml 生成protobuf message定义\n```go\nimport (\n    \"github.com/antlabs/tostruct/protobuf\"\n    \"github.com/antlabs/tostruct/option\"\n)\n\nfunc main() {\n\tall, err := Marshal([]byte(`{\"int\":3, \"float64\": 3.14, \"string\":\"hello\"}`), option.WithStructName(\"reqProtobuf\"))\n\tfmt.Println(err)\n\tos.Stdout.Write(all)\n}\n/*\nmessage reqProtobuf {\n    float64 Float64 = 1;\n    int64 Int = 2;\n    string String = 3;\n}\n*/\n```\n## 二、各种配置项函数用法\n### 2.1 option.WithSpecifyType 指定生成类型(支持json/yaml)\n```go\nobj := `\n{\n  \"action\": \"get\",\n  \"count\": 0,\n  \"data\": {\n    \"a123\": \"delivered\"\n  },\n  \"duration\": 5,\n  \"entities\": [],\n  \"timestamp\": 1542601830084,\n  \"uri\": \"http://XXXX/XXXX/XXXX/users/user1/offline_msg_status/123\"\n}\n  `\n// 默认对象是转成结构体的，比如这里的data成员，有些接口返回的key是变动的，比如key是用户名value是消息是否投递成功(假装在im系统中)\n// 此类业务就需要转成map[string]string类型，这里就可以用上option.WithSpecifyType\n// 传参的类型是map[string]string， key为json路径，value值是要指定的类型\nall, err := Marshal([]byte(obj), option.WithStructName(\"reqName\"), option.WithTagName(\"json\"), option.WithSpecifyType(map[string]string{\n\t\".data\": \"map[string]string\",\n}))\n\n// output all\ntype reqName struct {\n\tAction    string            `json:\"action\"`\n\tCount     int               `json:\"count\"`\n\tData      map[string]string `json:\"data\"`\n\tDuration  int               `json:\"duration\"`\n\tEntities  interface{}       `json:\"entities\"`\n\tTimestamp int               `json:\"timestamp\"`\n\tURI       string            `json:\"uri\"`\n}\n\n```\n### 2.2 option.WithTagNameFromKey tag直接使用key的名字(支持http header)\nhttp header比较特殊，传递的标准header头会有-符。可以使用option.WithTagNameFromKey()指定直接使用key的名字当作tag名(header:\"xxx\")这里的xxx\n```go\nh := http.Header{\n\t\"Content-Type\":  []string{\"application/json\"},\n\t\"Accept\": []string{\"application/json\"},\n}\n\nres, err := http.Marshal(h, option.WithStructName(\"test\"), option.WithTagNameFromKey())\n\n// output res\ntype test struct {\n\tAccept      string `header:\"Accept\"`\n\tContentType string `header:\"Content-Type\"`\n}\n```\n\n### 2.3 option.WithOutputFmtBefore 支持(json/yaml/http header/query string)\n获取格式代码之前的buf输出，方便debug\n```go\n\nobj := `{\"a\":\"b\"}`\nvar out bytes.Buffer\nall, err := json.Marshal([]byte(obj), option.WithStructName(\"reqName\"), option.WithTagName(\"json\"), option.WithOutputFmtBefore(\u0026out))\n_ = all\n_ = err\n```\n\n### 2.4 option.WithGetValue 支持(json/yaml)\n把json串序列化成struct字符串的时候，顺带提取json字符串里面指定的key值\n```go\nobj := `{\"a\":\"b\"}`\ngetValue := map[string]string{\n  \".a\": \"\",\n}\n\n_, err := json.Marshal([]byte(obj), option.WithStructName(\"reqName\"), option.WithTagName(\"json\"), option.WithGetValue(getValue))\nfmt.Println(getValue[\".a\"], \"b\"))\n```\n\n### 2.5 option.WithGetRawValue 支持(json/yaml/header/query string)\n把json串序列化成struct字符串的时候，顺带提取json字符串里面指定的key值, value是any(int/string/float64)类型\n```go\nobj := `{\"a\":\"b\"}`\ngetValue := map[string]any{\n  \".a\": \"\",\n}\n\n_, err := json.Marshal([]byte(obj), option.WithStructName(\"reqName\"), option.WithTagName(\"json\"), option.WithGetRawValue(getValue))\nfmt.Println(getValue[\".a\"], \"b\"))\n```\n### 2.6 option.WithUsePtrType 支持(json/yaml)\n```go\nobj := `\n{\n  \"string\": \"\",\n  \"int\": 0,\n  \"float64\": 3.1415,\n  \"bool\": false\n}\n`\nptrField := []string{\".string\", \".int\", \".float64\", \".bool\"} //指定字段名使用指针类型\n\nall, err := json.Marshal([]byte(obj), option.WithStructName(\"reqName\"), option.WithGetRawValue(ptrField))\nfmt.Printf(\"%s\\n\", all)\n// 输出:\n/*\ntype reqName struct {\n\tBool    *bool    `json:\"bool\"`\n\tFloat64 *float64 `json:\"float64\"`\n\tInt     *int     `json:\"int\"`\n\tString  *string  `json:\"string\"`\n}\n*/\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantlabs%2Ftostruct","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantlabs%2Ftostruct","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantlabs%2Ftostruct/lists"}