Skip to content

Instantly share code, notes, and snippets.

@jeteon
Last active February 7, 2024 14:28
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jeteon/e71fa21c1feb48fe4b5eeec045229a0c to your computer and use it in GitHub Desktop.
Save jeteon/e71fa21c1feb48fe4b5eeec045229a0c to your computer and use it in GitHub Desktop.
NodeJS script to parse the Google Maps "data" URL attribute into an array.
'use strict';
/**
* Basic code to parse the values in the "data" attribute in a Google Maps URL to an Array.
* There will likely still be some work to do to interpret the resulting Array.
*
* Based on information from:
* http://stackoverflow.com/a/34275131/1852838
* http://stackoverflow.com/a/24662610/1852838
*/
const util = require('util');
// Data string to be parsed
var str = '!3m1!4b1!4m20!4m19!1m5!1m1!1s0x1e955fe737bd22e5:0xf5b813675e007ba8!2m2!1d28.3023579!2d-25.7297871!1m5!1m1!1s0x1e955e5c875906fd:0xa65176214cdebc80!2m2!1d28.3374283!2d-25.7657075!1m5!1m1!1s0x1e9560c06dba5b73:0x57122f60632be1a1!2m2!1d28.274954!2d-25.7832822!3e0';
var parts = str.split('!').filter(function(s) { return s.length > 0; }),
root = [], // Root elemet
curr = root, // Current array element being appended to
m_stack = [root,], // Stack of "m" elements
m_count = [parts.length,]; // Number of elements to put under each level
parts.forEach(function(el) {
var kind = el.substr(1, 1),
value = el.substr(2);
// Decrement all the m_counts
for (var i = 0; i < m_count.length; i++) {
m_count[i]--;
}
if (kind === 'm') { // Add a new array to capture coming values
var new_arr = [];
m_count.push(value);
curr.push(new_arr);
m_stack.push(new_arr);
curr = new_arr;
}
else {
if (kind == 'b') { // Assuming these are boolean
curr.push(value == '1');
}
else if (kind == 'd' || kind == 'f') { // Float or double
curr.push(parseFloat(value));
}
else if (kind == 'i' || kind == 'u' || kind == 'e') { // Integer, unsigned or enum as int
curr.push(parseInt(value));
}
else { // Store anything else as a string
curr.push(value);
}
}
// Pop off all the arrays that have their values already
while (m_count[m_count.length - 1] === 0) {
m_stack.pop();
m_count.pop();
curr = m_stack[m_stack.length - 1];
}
});
console.log(util.inspect(root, { depth: null }));
@quinncomendant
Copy link

Nice script, thanks for this!

It doesn't seem to work with this Google Maps URL which has a data value of:

!3m1!4b1!4m85!2m84!5m82!17m1!1i28!17m1!1i114!17m1!1i7!17m1!1i81!17m1!1i88!17m1!1i115!17m1!1i71!17m1!1i54!17m1!1i77!17m1!1i285!17m1!1i41!17m1!1i37!17m1!1i117!17m1!1i119!17m1!1i120!17m1!1i121!17m1!1i122!17m1!1i118!17m1!1i17!17m1!1i42!17m1!1i64!17m1!1i56!17m1!1i87!17m1!1i2!17m1!1i127!17m1!1i46!17m1!1i128!17m1!1i59!17m1!1i86!17m1!1i58!17m1!1i148!17m1!1i26!17m1!1i72!17m1!1i61!17m1!1i129!17m1!1i131!17m1!1i75!17m1!1i3!17m1!1i12!17m1!1i136!17m1!1i39!6e3

The result is:

[
  [ true ],
  [
    [
      [
        'm1', 28,  'm1', 114, 'm1', 7,   'm1', 81,  'm1', 88,
        'm1', 115, 'm1', 71,  'm1', 54,  'm1', 77,  'm1', 285,
        'm1', 41,  'm1', 37,  'm1', 117, 'm1', 119, 'm1', 120,
        'm1', 121, 'm1', 122, 'm1', 118, 'm1', 17,  'm1', 42,
        'm1', 64,  'm1', 56,  'm1', 87,  'm1', 2,   'm1', 127,
        'm1', 46,  'm1', 128, 'm1', 59,  'm1', 86,  'm1', 58,
        'm1', 148, 'm1', 26,  'm1', 72,  'm1', 61,  'm1', 129,
        'm1', 131, 'm1', 75,  'm1', 3,   'm1', 12,  'm1', 136,
        'm1', 39
      ],
      3
    ]
  ]
]

Which doesn't look like it parsed correctly, does it?

I didn't manipulate the URL in any way, it's generated simply by:

  1. Open https://www.google.com/maps/
  2. Search for hotels near washington dc
  3. In the Brands filter, choose checkboxes for Hilton, Hyatt, IHG, Marriott and click Done.

@zack-the-worker
Copy link

Do you have encode function for this?

@richardDobron
Copy link

richardDobron commented Dec 28, 2023

@zack-the-worker

Do you have encode function for this?

if you don't mind the PHP language, check this: https://github.com/richardDobron/google-maps-data-parameter-parser

@zack-the-worker
Copy link

@zack-the-worker

Do you have encode function for this?

if you don't mind the PHP language, check this: https://github.com/richardDobron/google-maps-data-parameter-parser

Thank you, i was tried your script, it's works, however, after decode, then encode, the encoded output is not the same with first string, is it normal?

@richardDobron
Copy link

richardDobron commented Dec 29, 2023

@zack-the-worker

Try to create an issue, I have been using this script for a long time on different addresses, and it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment