Skip to content

Universal international address formatter in Go

License

Notifications You must be signed in to change notification settings

timonmasberg/address-formatter

Repository files navigation

Golang Address Formatter

This Address Formatter package is able to convert an address into many international formats of postal addresses based on OpenCage Configuration (or custom ones). You can use the provided address structure or use a map of address components.

Quality Gate Status Go Report Card codecov

Usage

Import

import (
    "fmt"
    "github.com/timonmasberg/address-formatter"
)

Set up your config files or use OpenCage Configuration (/conf)
Load config from config files:

config := addrFmt.LoadConfig(addrFmt.ConfigFiles{
            CountriesPath:     "templates/countries/worldwide.yaml",
            ComponentsPath:    "templates/components.yaml",
            StateCodesPath:    "templates/state_codes.yaml",
            CountryToLangPath: "templates/country2lang.yaml",
            CountyCodesPath:   "templates/county_codes.yaml",
            CountryCodesPath:  "templates/country_codes.yaml",
            AbbreviationFiles: "templates/abbreviations/*.yaml",
        })

You can choose between 3 output formats:

  1. Array (returns a slice where each entry represents an address component)
  2. OneLine (address components joined with a comma in one line)
  3. PostalFormat (valid postal format for letters etc with a trailing \n)
config.OutputFormat = addrFmt.PostalFormat

address :=  &addrFmt.Address{
    House:         "Bundestag",
    HouseNumber:   "1",
    Road:          "Platz der Republik",
    City:          "Berlin",
    Postcode:      "11011",
    State:         "Berlin",
    Country:       "Deutschland",
}

formattedAddress, err := addrFmt.FormatAddress(address, config)
if err != nil {
    fmt.Printf("Failed to format address: %v", err)
} else {
    fmt.Println(formattedAddress)
    /*
        Bundestag
        Platz der Republik 1
        11011 Berlin
        Deutschland
    */
}

If you have data from sources such as OSM you probably have a map of unknown data. This package can cleanup the map by using data from the configurations and turn it into an Address structure. You can also use MapToAddress directly if you are aware of the quality. Just make sure you add your component names to the component aliases as this package uses the names from OpenCageData.

    	// with unknown data such as from osm
addressMap := make(map[string]string)
addressMap["house"] = "Bundestag"
addressMap["house_number"] = "1"
addressMap["road"] = "Platz der Republik"
addressMap["postcode"] = "11011"
addressMap["state"] = "Berlin"
addressMap["country"] = "Deutschland"

address, err = addrFmt.GetFixedAddress(addressMap, config)
if err != nil {
    fmt.Printf("Fixing address failed: %v", err)
}

If you want to treat every unknown component name as an attention entry, set UnknownAsAttention to true

config.UnknownAsAttention = true

addressMap["mutti"] = "Angela Merkel"
addressMap["vati"] = "Frank-Walter Steinmeier"

address, err = addrFmt.GetFixedAddress(addressMap, config)
if err != nil {
    fmt.Printf("Fixing address failed: %v", err)
} else {
    fmt.Println(address.Attention)
    // Angela Merkel, Frank-Walter Steinmeier
}

Abbreviations tbd.

Testing

Load the config files from the submodule with copy-templates.cmd. Testing the formatter relies on testcase files. You can execute copy-testcases.cmd to use the OpenCageData testcases, or you can run the tests with your own. Just create them in the testcases folder with the same structure.

License

MIT