{"id":33122583,"url":"https://github.com/Boostport/address","last_synced_at":"2025-11-19T23:00:52.050Z","repository":{"id":37665040,"uuid":"128726638","full_name":"Boostport/address","owner":"Boostport","description":"Address is a Go library that validates and formats addresses using data generated from Google's Address Data Service","archived":false,"fork":false,"pushed_at":"2025-02-05T03:21:52.000Z","size":668,"stargazers_count":96,"open_issues_count":0,"forks_count":17,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-08-13T21:48:44.087Z","etag":null,"topics":["address","formatting","go","validation"],"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/Boostport.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":"2018-04-09T06:43:47.000Z","updated_at":"2025-08-05T10:07:33.000Z","dependencies_parsed_at":"2024-01-03T06:57:27.374Z","dependency_job_id":"23ee3761-265d-4e4b-a8aa-9c9e6aa143ac","html_url":"https://github.com/Boostport/address","commit_stats":{"total_commits":73,"total_committers":9,"mean_commits":8.11111111111111,"dds":"0.20547945205479456","last_synced_commit":"0b9e6de44e7b7b7a9e03b9550fc4a3d1fc3cb468"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/Boostport/address","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostport%2Faddress","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostport%2Faddress/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostport%2Faddress/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostport%2Faddress/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Boostport","download_url":"https://codeload.github.com/Boostport/address/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Boostport%2Faddress/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285342137,"owners_count":27155385,"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","status":"online","status_checked_at":"2025-11-19T02:00:05.673Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["address","formatting","go","validation"],"created_at":"2025-11-15T05:00:42.199Z","updated_at":"2025-11-19T23:00:52.031Z","avatar_url":"https://github.com/Boostport.png","language":"Go","funding_links":[],"categories":["Postal Addresses"],"sub_categories":[],"readme":"# Address\n[![GoDoc](https://godoc.org/github.com/Boostport/address?status.png)](https://godoc.org/github.com/Boostport/address)\n[![Tests Status](https://github.com/Boostport/address/workflows/Tests/badge.svg)](https://github.com/Boostport/address)\n[![Code Coverage](https://qlty.sh/gh/Boostport/projects/address/coverage.svg)](https://qlty.sh/gh/Boostport/projects/address)\n\nAddress is a Go library that validates and formats addresses using data generated from [Google's Address Data Service](https://chromium-i18n.appspot.com/ssl-address).\n\n## Installation\nInstall the library using Go modules. For example: `go get -u github.com/Boostport/address`.\n\n## Creating Addresses\nTo create a new address, use `New()`. If the address is invalid, an error will be returned.\n\n```go\npackage main\n\nimport (\n\t\"errors\"\n\t\"log\"\n\n\t\"github.com/Boostport/address\"\n)\n\nfunc main() {\n\taddr, err := address.NewValid(\n\t\taddress.WithCountry(\"AU\"), // Must be an ISO 3166-1 country code\n\t\taddress.WithName(\"John Citizen\"),\n\t\taddress.WithOrganization(\"Some Company Pty Ltd\"),\n\t\taddress.WithStreetAddress([]string{\n\t\t\t\"525 Collins Street\",\n\t\t}),\n\t\taddress.WithLocality(\"Melbourne\"),\n\t\taddress.WithAdministrativeArea(\"VIC\"), // If the country has a pre-defined list of admin areas (like here), you must use the key and not the name\n\t\taddress.WithPostCode(\"3000\"),\n\t)\n\n\tif err != nil {\n\t\t// If there was an error and you want to find out which validations failed, use errors.Is()\n\t\tif errors.Is(err, address.ErrInvalidCountryCode) {\n\t\t    log.Fatalf(\"Invalid country code\")\n\t\t}\n\t}\n\n\t// Use addr here\n}\n```\n\n### A note about administrative areas, localities and dependent localities\nAn address may contain the following subdivisions:\n- Administrative areas, such as a state, province, island, etc.\n- Localities such as cities.\n- Dependent localities such as districts, suburbs, etc.\n\nWhen creating an address, certain countries have a pre-defined list of administrative areas, localities and dependent localities.\nIn these cases, you **MUST** use the appropriate key when calling `WithAdministrativeArea()`, `WithLocality()` and `WithDependentLocality()`,\notherwise, the address will fail validation.\n\nIn terms of the keys, for administrative areas we use the ISO 3166-2 subdivision codes from Google's data set where possible. If there is no\nISO 3166-2 code available, we use the key defined in Google's data set. In these cases, the key is a unicode string (could be in languages other than \nEnglish).\n\nFor localities and dependent localities, there are generally no ISO codes, so we use the key defined in Google's data set. The key is a unicode string\nand can be in a language other than English.\n\nThe reason for doing this is that when storing an address into a database, we need to store the values in a canonical form. Since these keys are\nvery stable (in general), they are safe to store. If we need to provide a visual representation of the address, we can then use the key and a language\nto choose the appropriate display names.\n\nThis also allows us to do things such as rendering Canadian addresses both in French and English using a canonical address.\n\nThe library contains helpers where you can access these keys and the display names in different languages. More information available [below](#address-data-format).\n\n## Formatting Addresses\nThere are 2 formatters, the `DefaultFormatter` and a `PostalLabelFormatter`.\n\nIn addition, there 2 outputters, the `StringOutputter` and the `HTMLOutputter`. The outputter takes the formatted\naddress from the formatters and turn them into their respective string or HTML representations. The `Outputter` is\nan interface, so it's possible to implement your own version of the outputter if desired.\n\nIn some countries such as China, the address is formatted as major-to-minor (i.e. country -\u003e administrative division -\u003e locality ...).\nIt's possible to format it using a latinized format (address -\u003e dependent locality -\u003e locality ...) by setting the `Latinize` field in\nthe formatter to `true`.\n\nThis [example](examples/formatters/main.go) shows the difference between the 2 formatters and outputters (error checking omitted for brevity):\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/Boostport/address\"\n)\n\nfunc main() {\n\n\taddr, _ := address.NewValid(\n\t\taddress.WithCountry(\"AU\"),\n\t\taddress.WithName(\"John Citizen\"),\n\t\taddress.WithOrganization(\"Some Company Pty Ltd\"),\n\t\taddress.WithStreetAddress([]string{\n\t\t\t\"525 Collins Street\",\n\t\t}),\n\t\taddress.WithLocality(\"Melbourne\"),\n\t\taddress.WithAdministrativeArea(\"VIC\"),\n\t\taddress.WithPostCode(\"3000\"),\n\t)\n\n\tdefStringFormatter := address.DefaultFormatter{\n\t\tOutput: address.StringOutputter{},\n\t}\n\n\tdefHTMLFormatter := address.DefaultFormatter{\n\t\tOutput: address.HTMLOutputter{},\n\t}\n\n\tpostalStringFormatter := address.PostalLabelFormatter{\n\t\tOutput:            address.StringOutputter{},\n\t\tOriginCountryCode: \"FR\", // We are sending from France\n\t}\n\n\tpostalHTMLFormatter := address.PostalLabelFormatter{\n\t\tOutput:            address.HTMLOutputter{},\n\t\tOriginCountryCode: \"FR\", // We are sending from France\n\t}\n\n\tlang := \"en\" // Use the English names of the administrative areas, localities and dependent localities where possible\n\n\tfmt.Println(defStringFormatter.Format(addr, lang))\n\t/* Output\n\tSome Company Pty Ltd\n\tJohn Citizen\n\t525 Collins Street\n\tMelbourne Victoria 3000\n\tAustralia\n\t*/\n\t\n\tfmt.Println(defHTMLFormatter.Format(addr, lang))\n\t/* Output\n\t\u003cspan class=\"organization\"\u003eSome Company Pty Ltd\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"name\"\u003eJohn Citizen\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"address-line-1\"\u003e525 Collins Street\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"locality\"\u003eMelbourne\u003c/span\u003e \u003cspan class=\"administrative-area\"\u003eVictoria\u003c/span\u003e \u003cspan class=\"post-code\"\u003e3000\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"country\"\u003eAustralia\u003c/span\u003e\n\t*/\n\t\n\tfmt.Println(postalStringFormatter.Format(addr, lang))\n\t/* Output\n\tSome Company Pty Ltd\n\tJohn Citizen\n\t525 Collins Street\n\tMELBOURNE VIC 3000\n\tAUSTRALIE - AUSTRALIA\n\t*/\n\t\n\tfmt.Println(postalHTMLFormatter.Format(addr, lang))\n\t/* Output\n\t\u003cspan class=\"organization\"\u003eSome Company Pty Ltd\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"name\"\u003eJohn Citizen\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"address-line-1\"\u003e525 Collins Street\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"locality\"\u003eMELBOURNE\u003c/span\u003e \u003cspan class=\"administrative-area\"\u003eVIC\u003c/span\u003e \u003cspan class=\"post-code\"\u003e3000\u003c/span\u003e\u003cbr\u003e\n\t\u003cspan class=\"country\"\u003eAUSTRALIE - AUSTRALIA\u003c/span\u003e\n\t*/\n}\n```\n## Zones\nZones are useful for calculating things like shipping costs or tax rates. A `Zone` consists of multiple territories, with\neach `Territory` equivalent to a rule.\n\nTerritories are able to match addresses based on their `Country`, `AdministrativeArea`, `Locality`, `DependentLocality` and `PostCode`.\n\nNote that the `Country` must be an ISO 3166-1 country code, and if there are pre-defined lists of `AdministrativeArea`s, `Locality`, and `DependentLocality`\nfor the country, the key must be used.\n\nA quick [example](examples/zones/main.go):\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/Boostport/address\"\n)\n\nfunc main() {\n\taddr, _ := address.NewValid(\n\t\taddress.WithCountry(\"AU\"),\n\t\taddress.WithName(\"John Citizen\"),\n\t\taddress.WithOrganization(\"Some Company Pty Ltd\"),\n\t\taddress.WithStreetAddress([]string{\n\t\t\t\"525 Collins Street\",\n\t\t}),\n\t\taddress.WithLocality(\"Melbourne\"),\n\t\taddress.WithAdministrativeArea(\"VIC\"),\n\t\taddress.WithPostCode(\"3000\"),\n\t)\n\n\tfreeShippingToQLDAndNSW := address.Zone{\n\t\t{\n\t\t\tCountry:            \"AU\",\n\t\t\tAdministrativeArea: \"NSW\",\n\t\t},\n\t\t{\n\t\t\tCountry:            \"AU\",\n\t\t\tAdministrativeArea: \"QLD\",\n\t\t},\n\t}\n\n\tfmt.Println(freeShippingToQLDAndNSW.Contains(addr)) // false\n\n\tvictorianPostCodesExceptCarltonGetDiscount := address.Zone{\n\t\t{\n\t\t\tCountry: \"AU\",\n\t\t\tIncludedPostCodes: address.ExactMatcher{\n\t\t\t\tRanges: []address.PostCodeRange{\n\t\t\t\t\t{\n\t\t\t\t\t\tStart: 3000,\n\t\t\t\t\t\tEnd:   3996,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tStart: 8000,\n\t\t\t\t\t\tEnd:   8873,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tExcludedPostCodes: address.ExactMatcher{\n\t\t\t\tMatches: []string{\"3053\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfmt.Println(victorianPostCodesExceptCarltonGetDiscount.Contains(addr)) // true\n}\n```\n\n## Address Data Format\nIn a lot of cases, you might need to display a form to the user to enter their address.\n\nThere is the `ListCountries()` method to get a list of available countries in your chosen language\nand the `GetCountry()` method to get detailed address format information for a given country.\n\n`GetCountry()` returns a struct like so:\n```go\ntype CountryData struct {\n\tFormat                     string\n\tLatinizedFormat            string\n\tRequired                   []Field\n\tAllowed                    []Field\n\tDefaultLanguage            string\n\tAdministrativeAreaNameType FieldName\n\tLocalityNameType           FieldName\n\tDependentLocalityNameType  FieldName\n\tPostCodeNameType           FieldName\n\tPostCodeRegex              PostCodeRegexData\n\tAdministrativeAreas        map[string][]AdministrativeAreaData\n}\n```\n\nThe `Format` and `LatinizedFormat` fields are in Google's original formats (ex: `%O%n%N%n%A%n%C %S %Z` for Australia).\nA description of what the tokens represent is available [here](https://github.com/googlei18n/libaddressinput/wiki/AddressValidationMetadata).\n\n`Required` and `Allowed` represent fields that are required and allowed (not all allowed fields are required). The `Field` type\ncan be converted to Google's token name by calling the `Key()` method.\n\nFor administrative areas, the map contains a list of administrative areas grouped by the language they are in (the map's key).\nEach list is sorted according to the language they are in. Administrative areas may contain localities, and localities\nmay contain dependent localities. In all cases, each element would have an ID that you should use when creating an address or a zone.\n\nThere may also be post code validation regex. There may be further structs nested inside to validate post codes for an administrative area,\nlocality or dependent locality. These are keyed using the appropriate ID from the list of administrative areas.\n\n\n## Generating Data\n### Directly in your environment\nInstall stringer: `go get -u golang.org/x/tools/cmd/stringer`.\n\nTo generate the data and generate the `String()` functions for the constants, simply run `go generate` from the root of the project.\nThis will run stringer and the generator which will download the data from Google and convert the data into Go code.\n\n### Using docker\nRun `docker compose run generate`\n\n## License\nThis library is licensed under the Apache 2 License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBoostport%2Faddress","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FBoostport%2Faddress","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBoostport%2Faddress/lists"}