Understanding JSON Paths in Address Typeahead
The Address Typeahead functionality includes configuration in the workbench that uses JSON Path syntax, which is described in the JSON Path Structure section below.
For the Suggestion Response Mapping flipper, configuration uses two-level mapping to handle the array that contains nested Suggestion Response records and the individual fields within the array. This mapping is described in the Two-Level Mapping Functionality section below.
The complete workbench configuration is described in the STEP Workbench Configure Address Typeahead topic.
JSON Path Structure
JSON Paths are used to query the JSON response document for both address typeahead suggestion and selection responses. While in the address typeahead configuration editor, the user adds JSON Paths for fields in the Suggestion Response Mapping flipper, the Selection Response Mapping JSON Paths flipper, and the Error Handling flipper.
The JSON Path query language is similar to XPath for XML. JSON Paths indicate the path to a specific element in the JSON response which is extracted and displays in the Address Typeahead for the Web UI.
You can mix two types of JSON Path notation when expressing a path for address typeahead:
-
Dot notation - $.Items.*
-
Bracket notation - $['Items'][*]
Although the bracket notation is used in the address typeahead configuration editor examples, both notations produce the same results.
A JSON Path uses operators to create an expression for the path to a JSON document element.
For example, within an Address Typeahead configuration, the following operators (among others) can be used to extract data from the JSON selection response document.
Operator | Description |
---|---|
$ |
Represents the root node of a JSON structure, whether it is an object or an array. |
@ |
Represents the current node being processed. Typically, this is used as part of input expressions for predicates. In row 2 in the table below, suppose that the current node includes the types of countries array and the required data is the short name from the current node. |
* |
Wildcard; expresses all elements within the specified scope. For instance, Items[*] indicates all nodes inside a parent Items array. |
['property'] |
Selects the specified property in a parent object. |
[n] |
Selects the nth element from an array. Indexes are 0-based. |
[?(expression)] |
Filter expression, selects all elements in an object or array that match the specified filter. Returns a list. |
! |
Negates inside a filter. |
|| |
Logical OR; used to combine multiple filter expressions. |
&& |
Logical AND; used to combine multiple filter expressions. |
in |
Checks if the left-side value is present in the right-side list. Similar to the SQL 'IN' operator. String comparison is case-sensitive. |
An example of combining these operators for one of the JSON paths in the typeahead configuration is:
[?('locality' in @.types || (!'locality' in @.types && 'postal_town' in @.types))]
This example results in returning items that either have locality in types or they do not have locality but have postal town values.
Examples of JSON Path and Results
The Google Places suggestion and selection queries included below run for the specified URLs.
The following table includes a description of the data extracted from the URL, the JSON Path, and the results.
No | Data Extracted | JSON Path | Result |
---|---|---|---|
1 |
The array of predictions. In this example, there are 5 |
$['predictions'][*] |
All array elements under the Predictions |
2 |
The Latitude (line 40 in selection response) |
$['result']['geometry']['location']['lat'] |
56.10813 |
3 |
The ISO code (line 22 from selection response) |
$['result']['address_components'][?('country' in @.types)]['short_name'] |
["DK"] |
4 |
The City (line 13 from selection response) |
$['result']['address_components'][?('locality' in @.types || (!'locality' in @.types && 'postal_town' in @.types))]['long_name'] |
["Højbjerg"] |
Suggestion Request URL
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=axel&types=address&language=en&sessiontoken=a1552fc1-03d6-4eb8-a405-e230596f245f&key=[hidden API Key in use]
{
"predictions": [
{
"description": "Axel-Springer-Straße, Berlin, Germany",
"matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"place_id": "EiZBeGVsLVNwcmluZ2VyLVN0cmHDn2UsIEJlcmxpbiwgR2VybWFueSIuKiwKFAoSCdU8j9HXUahHEakSx1FDHkw1EhQKEgkBWQM_N06oRxFwO15bRiAhBA",
"reference": "EiZBeGVsLVNwcmluZ2VyLVN0cmHDn2UsIEJlcmxpbiwgR2VybWFueSIuKiwKFAoSCdU8j9HXUahHEakSx1FDHkw1EhQKEgkBWQM_N06oRxFwO15bRiAhBA",
"structured_formatting": {
"main_text": "Axel-Springer-Straße",
"main_text_matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"secondary_text": "Berlin, Germany"
},
"terms": [
{
"offset": 0,
"value": "Axel-Springer-Straße"
},
{
"offset": 22,
"value": "Berlin"
},
{
"offset": 30,
"value": "Germany"
}
],
"types": [
"route",
"geocode"
]
},
{
"description": "Axeltorv, Copenhagen Municipality, Denmark",
"matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"place_id": "EipBeGVsdG9ydiwgQ29wZW5oYWdlbiBNdW5pY2lwYWxpdHksIERlbm1hcmsiLiosChQKEgmBtxjNDVNSRhEW0gaMWQTS0xIUChIJiflw5SJTUkYRQk2g-SoIpbQ",
"reference": "EipBeGVsdG9ydiwgQ29wZW5oYWdlbiBNdW5pY2lwYWxpdHksIERlbm1hcmsiLiosChQKEgmBtxjNDVNSRhEW0gaMWQTS0xIUChIJiflw5SJTUkYRQk2g-SoIpbQ",
"structured_formatting": {
"main_text": "Axeltorv",
"main_text_matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"secondary_text": "Copenhagen Municipality, Denmark"
},
"terms": [
{
"offset": 0,
"value": "Axeltorv"
},
{
"offset": 10,
"value": "Copenhagen Municipality"
},
{
"offset": 35,
"value": "Denmark"
}
],
"types": [
"route",
"geocode"
]
},
{
"description": "Axel Dahlströms torg, Gothenburg, Sweden",
"matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"place_id": "EilBeGVsIERhaGxzdHLDtm1zIHRvcmcsIEdvdGhlbmJ1cmcsIFN3ZWRlbiIuKiwKFAoSCd82W4nY8k9GEZ0tttpBeMWmEhQKEglN7hrAYmJFRhE89fwlwqmKxQ",
"reference": "EilBeGVsIERhaGxzdHLDtm1zIHRvcmcsIEdvdGhlbmJ1cmcsIFN3ZWRlbiIuKiwKFAoSCd82W4nY8k9GEZ0tttpBeMWmEhQKEglN7hrAYmJFRhE89fwlwqmKxQ",
"structured_formatting": {
"main_text": "Axel Dahlströms torg",
"main_text_matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"secondary_text": "Gothenburg, Sweden"
},
"terms": [
{
"offset": 0,
"value": "Axel Dahlströms torg"
},
{
"offset": 22,
"value": "Gothenburg"
},
{
"offset": 34,
"value": "Sweden"
}
],
"types": [
"route",
"geocode"
]
},
{
"description": "Axel-Springer-Platz, Hamburg, Germany",
"matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"place_id": "EiVBeGVsLVNwcmluZ2VyLVBsYXR6LCBIYW1idXJnLCBHZXJtYW55Ii4qLAoUChIJYSiZoRCPsUcRFsBQT-6D-IgSFAoSCbkTGH6DYbFHEaA61nvyPSYE",
"reference": "EiVBeGVsLVNwcmluZ2VyLVBsYXR6LCBIYW1idXJnLCBHZXJtYW55Ii4qLAoUChIJYSiZoRCPsUcRFsBQT-6D-IgSFAoSCbkTGH6DYbFHEaA61nvyPSYE",
"structured_formatting": {
"main_text": "Axel-Springer-Platz",
"main_text_matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"secondary_text": "Hamburg, Germany"
},
"terms": [
{
"offset": 0,
"value": "Axel-Springer-Platz"
},
{
"offset": 21,
"value": "Hamburg"
},
{
"offset": 30,
"value": "Germany"
}
],
"types": [
"route",
"geocode"
]
},
{
"description": "Axel Kiers Vej, Højbjerg, Denmark",
"matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"place_id": "EiJBeGVsIEtpZXJzIFZlaiwgSMO4amJqZXJnLCBEZW5tYXJrIi4qLAoUChIJSYk_2y9ATEYR0fNhoFR6Dq8SFAoSCWE6wmVeQExGEVHw4kPhFeHp",
"reference": "EiJBeGVsIEtpZXJzIFZlaiwgSMO4amJqZXJnLCBEZW5tYXJrIi4qLAoUChIJSYk_2y9ATEYR0fNhoFR6Dq8SFAoSCWE6wmVeQExGEVHw4kPhFeHp",
"structured_formatting": {
"main_text": "Axel Kiers Vej",
"main_text_matched_substrings": [
{
"length": 4,
"offset": 0
}
],
"secondary_text": "Højbjerg, Denmark"
},
"terms": [
{
"offset": 0,
"value": "Axel Kiers Vej"
},
{
"offset": 16,
"value": "Højbjerg"
},
{
"offset": 26,
"value": "Denmark"
}
],
"types": [
"route",
"geocode"
]
}
],
"status": "OK"
}
After selecting the 'Axel Kiers Vej, 8270 Højbjerg, Denmark' suggestion (with ID: place_id=EiJBeGVsIEtpZXJzIFZlaiwgSMO4amJqZXJnLCBEZW5tYXJrIi4qLAoUChIJSYk_2y9ATEYR0fNhoFR6Dq8SFAoSCWE6wmVeQExGEVHw4kPhFeHp) from the Suggestion Request URL above, the Selection Request URL below produces the following JSON Path Response.
Selection Request URL
https://maps.googleapis.com/maps/api/place/details/json?types=address&language=en&sessiontoken=9f08e2d7-6df3-437b-b009-d7fa699b0dea&place_id=EiJBeGVsIEtpZXJzIFZlaiwgSMO4amJqZXJnLCBEZW5tYXJrIi4qLAoUChIJSYk_2y9ATEYR0fNhoFR6Dq8SFAoSCWE6wmVeQExGEVHw4kPhFeHp&key=[hidden API Key in use]
JSON Path Response
{
"html_attributions": [],
"result": {
"address_components": [
{
"long_name": "Axel Kiers Vej",
"short_name": "Axel Kiers Vej",
"types": [
"route"
]
},
{
"long_name": "Højbjerg",
"short_name": "Højbjerg",
"types": [
"locality",
"political"
]
},
{
"long_name": "Denmark",
"short_name": "DK",
"types": [
"country",
"political"
]
},
{
"long_name": "8270",
"short_name": "8270",
"types": [
"postal_code"
]
}
],
"adr_address": "<span class=\"street-address\">Axel Kiers Vej</span>, <span class=\"postal-code\">8270</span> <span class=\"locality\">Højbjerg</span>, <span class=\"country-name\">Denmark</span>",
"formatted_address": "Axel Kiers Vej, 8270 Højbjerg, Denmark",
"geometry": {
"location": {
"lat": 56.10813,
"lng": 10.162714
},
"viewport": {
"northeast": {
"lat": 56.10947898029151,
"lng": 10.1640629802915
},
"southwest": {
"lat": 56.10678101970851,
"lng": 10.1613650197085
}
}
},
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/geocode-71.png",
"icon_background_color": "#7B9EB0",
"icon_mask_base_uri": "https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet",
"name": "Axel Kiers Vej",
"place_id": "EidBeGVsIEtpZXJzIFZlaiwgODI3MCBIw7hqYmplcmcsIERlbm1hcmsiLiosChQKEglJiT_bL0BMRhHR82GgVHoOrxIUChIJYTrCZV5ATEYRUfDiQ-EV4ek",
"reference": "EidBeGVsIEtpZXJzIFZlaiwgODI3MCBIw7hqYmplcmcsIERlbm1hcmsiLiosChQKEglJiT_bL0BMRhHR82GgVHoOrxIUChIJYTrCZV5ATEYRUfDiQ-EV4ek",
"types": [
"route"
],
"url": "https://maps.google.com/?q=Axel+Kiers+Vej,+8270+H%C3%B8jbjerg,+Denmark&ftid=0x464c402fdb3f8949:0xaf0e7a54a061f3d1",
"utc_offset": 120,
"vicinity": "Højbjerg"
},
"status": "OK"
}
Two-Level Mapping Functionality
Unlike the other configuration flippers, the Suggestion Response Mapping flipper uses two-level mapping to handle the array that contains nested Suggestion Response records and the individual fields within the array.
The first-level mapping includes the 'Suggestion Array JSON Path' query $[‘Items’][*]. This mapping creates a new JSON document behind the scenes which is used to extract all data and present transformed records in a human-readable format.
These parameters are used for the second-level mapping:
-
The Display Text JSON Path parameter displays a typeahead suggestion.
-
The Suggestion Type JSON Path and the Suggestion Type Selection Value parameters are required to display a typeahead suggestion if the value is an address or request further data if the value is a street.
-
The Address ID JSON Path is required for the service to provide the full address after a suggestion is chosen.
When a suggestion response array includes a list of multiple values, indicating multiple suggestions, the configuration requires two (2) JSON Paths, one for the Text field and one for the Description field. This allows the Web UI to present the Display Text as Text and Description values, concatenated with ', ' (comma and a space). The comma separator cannot be manually changed.
Note: Google Places does not use multiple paths.
Example of Concatenation of Multiple Values
The following JSON suggestion response array for Loqate includes two (2) records:
{"Items":[{"Id":"DK|TT|B|12080001900753|6","Type":"Address","Text":"Elmevej 6","Highlight":"0-7,8-9","Description":"4863 Eskilstrup"}, {"Id":"DK|TT|B|12080000210081|6","Type":"Address","Text":"Elmevej 6","Highlight":"0-7,8-9","Description":"4050 Skibby"}]}
For these records, two suggestions (display texts) are returned as shown below:
-
Elmevej 6, 4863 Eskilstrup
-
Elmevej 6, 4050 Skibby
Example of Two-Level Mapping
The following is a JSON response payload extracted from the first-level JSON Path from the suggestion endpoint which is a record of arrays containing three (3) nested records:
{"Items":[ { "Id":"DK|TT|DAN|SYDDANMARK-RUDKUDKØBING—LØNKILDEVEJ", "Type":"Street", "Text":"Lønkildevej", "Highlight":"0-3", "Description":"5900 Rudkøbing - 41 Addresses" }, { "Id":"DK|TT|DAN|SJÆLLAND-ROSKILDE--LØNBJERGPARKEN", "Type":"Street", "Highlight":"0-3", "Description":"4000 Roskilde - 33 Addresses" }, { "Id":"DK|TT|DAN|SJÆLLAND-ROSKILDE--LØNBJERGTOFTEN", "Type":"Street", "Text":"Lønbjergtoften", "Highlight":"0-3", "Description":"4000 Roskilde - 10 Addresses" } ]}
To retrieve the necessary elements, the system creates a second-level JSON document (shown below) to extract the data. The system iteratively checks each record in the array in the JSON document to extract data to be transformed to ID, Display Text, and Type for each suggestion and displayed in the Web UI.
-
Display Text JSON Path: $[‘Text’]
-
Suggestion Type JSON Path: $[‘Type’]
-
Address ID JSON Path: $[‘Id’]
[ { "Id":"DK|TT|DAN|SYDDANMARK-RUDK\\u00D8BING--L\\u00D8NKILDEVEJ", "Type":"Street", "Text":"L\\u00F8nkildevej", "Highlight":"0-3", "Description":"5900 Rudk\\u00F8bing - 41 Addresses" }, { "Id":"DK|TT|DAN|SJ\\u00C6LLAND-ROSKILDE--L\\u00D8NBJERGPARKEN", "Type":"Street", "Highlight":"0-3", "Description":"4000 Roskilde - 33 Addresses" }, { "Id":"DK|TT|DAN|SJ\\u00C6LLAND-ROSKILDE--L\\u00D8NBJERGTOFTEN", "Type":"Street", "Text":"L\\u00F8nbjergtoften", "Highlight":"0-3", "Description":"4000 Roskilde - 10 Addresses" } ]
The system applies the JSON paths to every record.
For the first record shown above, the transformed data is:
-
Display Text (concatenation by comma / space of Text + Description): Lønkildevej, 5900 Rudkøbing - 41 Addresses
-
Suggestion Type: Street
-
Address ID: DK|TT|DAN|SYDDANMARK-RUDKØBING—LØNKILDEVEJ
For the second record shown above, the transformed data is:
-
Display Text (concatenation by comma / space of Text + Description field): No Display Text
-
Suggestion Type: Street
-
Address ID: DK|TT|DAN|SJÆLLAND-ROSKILDE--LØNBJERGPARKEN
For the third record shown above, the transformed data is:
-
Display Text (concatenation by comma / space of Text + Description field): Lønbjergtoften, 4000 Roskilde - 10 Addresses
-
Suggestion Type: Street
-
Address ID: DK|TT|DAN|SJÆLLAND-ROSKILDE--LØNBJERGTOFTEN
Note: When text is missing from the response, it results in an error message in the Web UI. This can happen with every property data field inside a record. For example, the second record above is missing a value for Display Text.