{"id":25176991,"url":"https://github.com/lovromazgon/jsonpoly","last_synced_at":"2025-07-04T03:34:44.180Z","repository":{"id":246740696,"uuid":"821532547","full_name":"lovromazgon/jsonpoly","owner":"lovromazgon","description":"Handle polymorphic JSON objects in Go.","archived":false,"fork":false,"pushed_at":"2024-07-05T12:24:01.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T22:16:11.905Z","etag":null,"topics":["go","json","polymorphic"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lovromazgon.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":"2024-06-28T18:58:59.000Z","updated_at":"2024-07-05T12:24:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"f7048344-87a5-4b6a-9811-fa760245d828","html_url":"https://github.com/lovromazgon/jsonpoly","commit_stats":null,"previous_names":["lovromazgon/jsonpoly"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovromazgon%2Fjsonpoly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovromazgon%2Fjsonpoly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovromazgon%2Fjsonpoly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovromazgon%2Fjsonpoly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lovromazgon","download_url":"https://codeload.github.com/lovromazgon/jsonpoly/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247107830,"owners_count":20884797,"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":["go","json","polymorphic"],"created_at":"2025-02-09T13:20:01.653Z","updated_at":"2025-04-04T01:42:46.066Z","avatar_url":"https://github.com/lovromazgon.png","language":"Go","readme":"# JSONPoly\n\n[![License](https://img.shields.io/github/license/lovromazgon/jsonpoly)](https://github.com/lovromazgon/jsonpoly/blob/main/LICENSE)\n[![Test](https://github.com/lovromazgon/jsonpoly/actions/workflows/test.yml/badge.svg)](https://github.com/lovromazgon/jsonpoly/actions/workflows/test.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/lovromazgon/jsonpoly)](https://goreportcard.com/report/github.com/lovromazgon/jsonpoly)\n[![Go Reference](https://pkg.go.dev/badge/github.com/lovromazgon/jsonpoly.svg)](https://pkg.go.dev/github.com/lovromazgon/jsonpoly)\n\nUtilities for marshalling and unmarshalling polymorphic JSON objects in Go\nwithout generating code.\n\n## Usage\n\n```\ngo get github.com/lovromazgon/jsonpoly@latest\n```\n\nSay that you have an interface `Shape` and two structs `Triangle` and `Square`\nthat implement it. The structs have a method `Kind` that returns the name of\nthe shape.\n\n```go\npackage shapes\n\ntype Shape interface {\n\tKind() string\n}\n\nfunc (Triangle) Kind() string { return \"triangle\" }\nfunc (Square) Kind() string   { return \"square\" }\n\ntype Square struct {\n\tTopLeft [2]int `json:\"top-left\"`\n\tWidth   int    `json:\"width\"`\n}\n\ntype Triangle struct {\n\tP0 [2]int `json:\"p0\"`\n\tP1 [2]int `json:\"p1\"`\n\tP2 [2]int `json:\"p2\"`\n}\n```\n\nYou need to define a type that implements the `jsonpoly.Helper` interface and\ncan marshal and unmarshal the field(s) used to determine the type of the object.\nIn this case, the field is `kind`. You also need to define a map that maps the\nvalues of the field to the types.\n\n```go\nvar knownShapes = map[string]Shape{\n\tTriangle{}.Kind(): Triangle{},\n\tSquare{}.Kind():   Square{},\n}\n\ntype ShapeJSONHelper struct {\n\tKind string `json:\"kind\"`\n}\n\nfunc (h *ShapeJSONHelper) Get() Shape {\n\treturn knownShapes[h.Kind]\n}\n\nfunc (h *ShapeJSONHelper) Set(s Shape) {\n\th.Kind = s.Kind()\n}\n```\n\nNow you can marshal and unmarshal polymorphic JSON objects using `jsonpoly.Container`.\n\n```go\ninputShape := Square{TopLeft: [2]int{1, 2}, Width: 4}\n\nvar c jsonpoly.Container[Shape, *ShapeJSONHelper]\nc.Value = inputShape\n\nb, err := json.Marshal(c)\nfmt.Println(string(b)) // {\"kind\":\"square\",\"top-left\":[1,2],\"width\":4}\n\nc.Value = nil // reset before unmarshalling\nerr = json.Unmarshal(b, \u0026c)\nfmt.Printf(\"%T\\n\", c.Value) // shapes.Square\n```\n\nAlso check out the\n[marshalling](https://pkg.go.dev/github.com/lovromazgon/jsonpoly#example-Container-Marshal)\nand [unmarshalling](https://pkg.go.dev/github.com/lovromazgon/jsonpoly#example-Container-Unmarshal)\nexamples on the package documentation.\n\n## FAQ\n\n### How is this different than [`github.com/polyfloyd/gopolyjson`](https://github.com/polyfloyd/gopolyjson)?\n\n`gopolyjson` is a great package, but it has its limitations. Here's a list of\ndifferences that can help you determine what package to use:\n\n- `gopolyjson` requires you to add a private method to your interface without\n  parameters or return arguments. As a consequence, you have to put all types\n  that implement the interface in the same package. `jsonpoly` does not require\n  you to add any methods to your types.\n- `gopolyjson` requires you to generate code for each type you want to serialize.\n  Since the generated code adds methods to the types, you can not generate the\n  code for types from external packages. `jsonpoly` works without generating code.\n- Because `gopolyjson` uses generated code, it can be faster than `jsonpoly`.\n- `gopolyjson` only supports a single field at the root of the JSON to determine\n  the type of the object, while `jsonpoly` supports multiple fields.\n- `gopolyjson` does not handle unknown types which can be an issue with\n  backwards compatibility. `jsonpoly` can handle unknown types by having a\n  \"catch-all\" type.\n\n### How can I handle unknown types?\n\nIf you want to handle unknown types, you can define a \"catch-all\" type. The type\nshould be returned by the `Get` method of the `jsonpoly.Helper` implementation\nwhenever the type of the object is not recognized.\n\nKeep in mind that the field used to determine the type of the object should be\nmarked with the `json:\"-\"` tag, as it is normally handled by the helper. Not\ndoing so will result in duplicating the field.\n\n```go\ntype Unknown struct {\n    XKind string `json:\"-\"`\n    json.RawMessage // Store the raw json if needed.\n}\n\nfunc (u Unknown) Kind() string { return u.XKind }\n\ntype ShapeJSONHelper struct {\n    Kind string `json:\"kind\"`\n}\n\nfunc (h *ShapeJSONHelper) Get() Shape {\n    s, ok := knownShapes[h.Kind]\n    if !ok {\n        return Unknown{XKind: h.Kind}\n    }\n    return s\n}\n```\n\n### Can I use multiple fields to determine the type of the object?\n\nYes, you can use any number of fields to determine the type of the object. You\njust need to define a struct that contains all the fields and implements the\n`jsonpoly.Helper` interface.\n\nFor more information on how to do this, check the [`example`](./example) directory.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovromazgon%2Fjsonpoly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flovromazgon%2Fjsonpoly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovromazgon%2Fjsonpoly/lists"}