Skip to content

Changing the Appearance of Results in the Server API🔗

The Nominatim Server API offers a number of formatting options that present search results in different output formats. These results only contain a subset of all the information that Nominatim has about the result. This page explains how to adapt the result output or add additional result formatting.

Defining custom result formatting🔗

To change the result output, you need to place a file api/v1/format.py into your project directory. This file needs to define a single variable dispatch containing a FormatDispatcher. This class serves to collect the functions for formatting the different result types and offers helper functions to apply the formatters.

There are two ways to define the dispatch variable. If you want to reuse the default output formatting and just make some changes or add an additional format type, then import the dispatch object from the default API:

from nominatim_api.v1.format import dispatch as dispatch

If you prefer to define a completely new result output, then you can create an empty dispatcher object:

from nominatim_api import FormatDispatcher

dispatch = FormatDispatcher()

The formatting function🔗

The dispatcher organises the formatting functions by format and result type. The format corresponds to the format parameter of the API. It can contain one of the predefined format names or you can invent your own new format.

API calls return data classes or an array of a data class which represent the result. You need to make sure there are formatters defined for the following result types:

  • StatusResult (single object, returned by /status)
  • DetailedResult (single object, returned by /details)
  • SearchResults (list of objects, returned by /search)
  • ReverseResults (list of objects, returned by /reverse and /lookup)
  • RawDataList (simple object, returned by /deletable and /polygons)

A formatter function has the following signature:

def format_func(result: ResultType, options: Mapping[str, Any]) -> str

The options dictionary contains additional information about the original query. See the reference below about the possible options.

To set the result formatter for a certain result type and format, you need to write the format function and decorate it with the format_func decorator.

For example, let us extend the result for the status call in text format and add the server URL. Such a formatter would look like this:

from nominatim_api import StatusResult

@dispatch.format_func(StatusResult, 'text')
def _format_status_text(result, _):
    header = 'Status for server nominatim.openstreetmap.org'
    if result.status:
        return f"{header}\n\nERROR: {result.message}"

    return f"{header}\n\nOK"

If your dispatcher is derived from the default one, then this definition will overwrite the original formatter function. This way it is possible to customize the output of selected results.

Adding new formats🔗

You may also define a completely different output format. This is as simple as adding formatting functions for all result types using the custom format name:

from nominatim_api import StatusResult

@dispatch.format_func(StatusResult, 'chatty')
def _format_status_text(result, _):
    if result.status:
        return f"The server is currently not running. {result.message}"

    return "Good news! The server is running just fine."

That's all. Nominatim will automatically pick up the new format name and will allow the user to use it. There is no need to implement formatter functions for all the result types, when you invent a new one. The available formats will be determined for each API endpoint separately. To find out which formats are available, you can use the --list-formats option of the CLI tool:

me@machine:planet-project$ nominatim status --list-formats
2024-08-16 19:54:00: Using project directory: /home/nominatim/planet-project
text
json
chatty
debug
me@machine:planet-project$

The debug format listed in the last line will always appear. It is a special format that enables debug output via the command line (the same as the debug=1 parameter enables for the server API). To not clash with this built-in function, you shouldn't name your own format 'debug'.

Content type of new formats🔗

All responses will be returned with the content type application/json by default. If your format produces a different content type, you need to configure the content type with the set_content_type() function.

For example, the 'chatty' format above returns just simple text. So the content type should be set up as:

from nominatim_api.server.content_types import CONTENT_TEXT

dispatch.set_content_type('chatty', CONTENT_TEXT)

The content_types module used above provides constants for the most frequent content types. You set the content type to an arbitrary string, if the content type you need is not available.

Formatting error messages🔗

Any exception thrown during processing of a request is given to a special error formatting function. It takes the requested content type, the status code and the error message. It should return the error message in a form appropriate for the given content type.

You can overwrite the default formatting function with the decorator error_format_func:

import nominatim_api.server.content_types as ct

@dispatch.error_format_func
def _format_error(content_type: str, msg: str, status: int) -> str:
    if content_type == ct.CONTENT_XML:
        return f"""<?xml version="1.0" encoding="UTF-8" ?>
                     <message>{msg}</message>
                """
    if content_type == ct.CONTENT_JSON:
        return f'"{msg}"'

    return f"ERROR: {msg}"

Debugging custom formatters🔗

The easiest way to try out your custom formatter is by using the Nominatim CLI commands. Custom formats can be chosen with the --format parameter:

me@machine:planet-project$ nominatim status --format chatty
2024-08-16 19:54:00: Using project directory: /home/nominatim/planet-project
Good news! The server is running just fine.
me@machine:planet-project$

They will also emit full error messages when there is a problem with the code you need to debug.

Danger

In some cases, when you make an error with your import statement, the CLI will not give you an error but instead tell you, that the API commands are no longer available:

me@machine: nominatim status
usage: nominatim [-h] [--version] {import,freeze,replication,special-phrases,add-data,index,refresh,admin} ...
nominatim: error: argument subcommand: invalid choice: 'status'

This happens because the CLI tool is meant to still work when the nominatim-api package is not installed. Import errors involving nominatim_api are interpreted as "package not installed".

Use the help command to find out which is the offending import that could not be found:

me@machine: nominatim -h
... [other help text] ...
Nominatim API package not found (was looking for module: nominatim_api.xxx).

Reference🔗

FormatDispatcher🔗

Container for formatting functions for results. Functions can conveniently be added by using decorated functions.

error_format_func(func) 🔗

Decorator for a function that formats error messges. There is only one error formatter per dispatcher. Using the decorator repeatedly will overwrite previous functions.

format_error(content_type, msg, status) 🔗

Convert the given error message into a response string taking the requested content_type into account.

Change the format using the error_format_func decorator.

format_func(result_class, fmt) 🔗

Decorator for a function that formats a given type of result into the selected format.

format_result(result, fmt, options) 🔗

Convert the given result into a string using the given format.

The format is expected to be in the list returned by list_formats().

get_content_type(fmt) 🔗

Return the content type for the given format.

If no explicit content type has been defined, then JSON format is assumed.

list_formats(result_type) 🔗

Return a list of formats supported by this formatter.

set_content_type(fmt, content_type) 🔗

Set the content type for the given format. This is the string that will be returned in the Content-Type header of the HTML response, when the given format is choosen.

supports_format(result_type, fmt) 🔗

Check if the given format is supported by this formatter.

JsonWriter🔗

JSON encoder that renders the output directly into an output stream. This is a very simple writer which produces JSON in a compact as possible form.

The writer does not check for syntactic correctness. It is the responsibility of the caller to call the write functions in an order that produces correct JSON.

All functions return the writer object itself so that function calls can be chained.

__call__() 🔗

Return the rendered JSON content as a string. The writer remains usable after calling this function.

end_array() 🔗

Write the closing bracket of a JSON array.

end_object() 🔗

Write the closing bracket of a JSON object.

float(value, precision) 🔗

Write out a float value with the given precision.

key(name) 🔗

Write the key string of a JSON object.

keyval(key, value) 🔗

Write out an object element with the given key and value. This is a shortcut for calling 'key()', 'value()' and 'next()'.

keyval_not_none(key, value, transform=None) 🔗

Write out an object element only if the value is not None. If 'transform' is given, it must be a function that takes the value type and returns a JSON encodable type. The transform function will be called before the value is written out.

next() 🔗

Write out a delimiter comma between JSON object or array elements.

raw(raw_json) 🔗

Write out the given value as is. This function is useful if a value is already available in JSON format.

start_array() 🔗

Write the opening bracket of a JSON array.

start_object() 🔗

Write the open bracket of a JSON object.

value(value) 🔗

Write out a value as JSON. The function uses the json.dumps() function for encoding the JSON. Thus any value that can be encoded by that function is permissible here.

Options for different result types🔗

This section lists the options that may be handed in with the different result types in the v1 version of the Nominatim API.

StatusResult🔗

None.

DetailedResult🔗

Option Description
locales Locale object for the requested language(s)
group_hierarchy Setting of group_hierarchy parameter
icon_base_url (optional) URL pointing to icons as set in NOMINATIM_MAPICON_URL

SearchResults🔗

Option Description
query Original query string
more_url URL for requesting additional results for the same query
exclude_place_ids List of place IDs already returned
viewbox Setting of viewbox parameter
extratags Setting of extratags parameter
namedetails Setting of namedetails parameter
addressdetails Setting of addressdetails parameter

ReverseResults🔗

Option Description
query Original query string
extratags Setting of extratags parameter
namedetails Setting of namedetails parameter
addressdetails Setting of addressdetails parameter

RawDataList🔗

None.