From 0bf687dedb941cd2f651607167d53b15b781489d Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:09:56 -0400 Subject: [PATCH 01/12] PEP8 fixes --- json2kml.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/json2kml.py b/json2kml.py index 34988f0..6eec4a7 100644 --- a/json2kml.py +++ b/json2kml.py @@ -1,13 +1,13 @@ -##################################################################################### +############################################################################### # Python script to convert Google Maps JSON file to a KML file # Copyright (C) 2017 Dimitri Souza # https://github.com/dmrsouza/json2kml -##################################################################################### +############################################################################### # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License v3 as published by # the Free Software Foundation. -##################################################################################### - +############################################################################### + import json import simplekml import sys @@ -20,33 +20,33 @@ # when calling print titles inside the loop sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) -print ('Opening file "'+inputFile+'"') +print('Opening file "'+inputFile+'"') + +with open(inputFile) as jsonFile: + data = json.load(jsonFile) -with open (inputFile) as jsonFile: - data = json.load (jsonFile) - -kml = simplekml.Kml () +kml = simplekml.Kml() kml.document.name = outputFile count = 0 for place in data["features"]: if place["type"] == "Feature": title = place["properties"]["Title"] - print ('Parsing place "'+title+'"') - + print('Parsing place "'+title+'"') + placeLocation = place["properties"]["Location"] lon = place["geometry"]["coordinates"][0] lat = place["geometry"]["coordinates"][1] - + if "Address" in placeLocation: - address = placeLocation ["Address"] + address = placeLocation["Address"] else: address = "N/A" - - kml.newpoint (name=title, coords=[(lon,lat)], address=address) + + kml.newpoint(name=title, coords=[(lon, lat)], address=address) count += 1 - -print ('Saving file "'+outputFile+'"') -kml.save (outputFile) -print ('Done! Total of '+str(count)+' places saved to the KML file.') +print('Saving file "'+outputFile+'"') +kml.save(outputFile) + +print('Done! Total of '+str(count)+' places saved to the KML file.') From 457f7c7d52daa32236417b14683ea959ceaf80e5 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:12:43 -0400 Subject: [PATCH 02/12] Update to use f strings --- json2kml.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/json2kml.py b/json2kml.py index 6eec4a7..dae826a 100644 --- a/json2kml.py +++ b/json2kml.py @@ -20,7 +20,7 @@ # when calling print titles inside the loop sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) -print('Opening file "'+inputFile+'"') +print(f'Opening file "{inputFile}"') with open(inputFile) as jsonFile: data = json.load(jsonFile) @@ -32,7 +32,7 @@ for place in data["features"]: if place["type"] == "Feature": title = place["properties"]["Title"] - print('Parsing place "'+title+'"') + print(f'Parsing place "{title}"') placeLocation = place["properties"]["Location"] lon = place["geometry"]["coordinates"][0] @@ -46,7 +46,7 @@ kml.newpoint(name=title, coords=[(lon, lat)], address=address) count += 1 -print('Saving file "'+outputFile+'"') +print(f'Saving file "{outputFile}"') kml.save(outputFile) -print('Done! Total of '+str(count)+' places saved to the KML file.') +print(f'Done! Total of {count} places saved to the KML file.') From e606814e65558f89786e5b6ceea49d3f070e53db Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:14:02 -0400 Subject: [PATCH 03/12] Add encoding='utf8' UnicodeDecodeError: 'charmap' codec can't decode byte ... character maps to --- json2kml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json2kml.py b/json2kml.py index dae826a..84715a7 100644 --- a/json2kml.py +++ b/json2kml.py @@ -22,7 +22,7 @@ print(f'Opening file "{inputFile}"') -with open(inputFile) as jsonFile: +with open(inputFile, encoding='utf8') as jsonFile: data = json.load(jsonFile) kml = simplekml.Kml() From c8f0bd4fecb12b299e344d79ad3570ea36da7af0 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:17:20 -0400 Subject: [PATCH 04/12] Comment out sys.stdout UnsupportedOperation: detach Shouldn't be necessary in modern interpreters? --- json2kml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json2kml.py b/json2kml.py index 84715a7..94da3f4 100644 --- a/json2kml.py +++ b/json2kml.py @@ -18,7 +18,7 @@ # JSON Encoding is UTF-8. Change stdout to UTF-8 to prevent encoding error # when calling print titles inside the loop -sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) +# sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) print(f'Opening file "{inputFile}"') From 1a55c4b99c8cb9f2f6aab4e3dff29f613795d8bc Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:20:37 -0400 Subject: [PATCH 05/12] Missing address to None instead of "N/A" string So it doesn't display at all --- json2kml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json2kml.py b/json2kml.py index 94da3f4..e519800 100644 --- a/json2kml.py +++ b/json2kml.py @@ -41,7 +41,7 @@ if "Address" in placeLocation: address = placeLocation["Address"] else: - address = "N/A" + address = None kml.newpoint(name=title, coords=[(lon, lat)], address=address) count += 1 From b4dfbf89af6352a4402c066bde2ac2d972662635 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:39:10 -0400 Subject: [PATCH 06/12] Put outputFile in same folder, same name as input --- json2kml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json2kml.py b/json2kml.py index e519800..2fa8f66 100644 --- a/json2kml.py +++ b/json2kml.py @@ -14,7 +14,7 @@ import codecs inputFile = "Saved Places.json" -outputFile = "Saved Places.kml" +outputFile = f'{inputFile[:-5]} [json2kml.py].kml' # JSON Encoding is UTF-8. Change stdout to UTF-8 to prevent encoding error # when calling print titles inside the loop From 41906fa1bd2d9194dc9a0816aa3fbd0aa691d7b9 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 12:55:21 -0400 Subject: [PATCH 07/12] Use html.escape on titles and addresses An address of the form `Avenue U &, E 33rd St` was causing ExpatError: not well-formed (invalid token) Because XML requires it to be encoded as & --- json2kml.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/json2kml.py b/json2kml.py index 2fa8f66..d5a3841 100644 --- a/json2kml.py +++ b/json2kml.py @@ -12,6 +12,7 @@ import simplekml import sys import codecs +import html inputFile = "Saved Places.json" outputFile = f'{inputFile[:-5]} [json2kml.py].kml' @@ -31,7 +32,7 @@ count = 0 for place in data["features"]: if place["type"] == "Feature": - title = place["properties"]["Title"] + title = html.escape(place["properties"]["Title"]) print(f'Parsing place "{title}"') placeLocation = place["properties"]["Location"] @@ -39,7 +40,7 @@ lat = place["geometry"]["coordinates"][1] if "Address" in placeLocation: - address = placeLocation["Address"] + address = html.escape(placeLocation["Address"]) else: address = None From 22335183939ab98c5a3af0a4dff54a7b9248b781 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 13:04:58 -0400 Subject: [PATCH 08/12] "title" to "name", since that's used in KML tag --- json2kml.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/json2kml.py b/json2kml.py index d5a3841..34d7963 100644 --- a/json2kml.py +++ b/json2kml.py @@ -32,8 +32,8 @@ count = 0 for place in data["features"]: if place["type"] == "Feature": - title = html.escape(place["properties"]["Title"]) - print(f'Parsing place "{title}"') + name = html.escape(place["properties"]["Title"]) + print(f'Parsing place "{name}"') placeLocation = place["properties"]["Location"] lon = place["geometry"]["coordinates"][0] @@ -44,7 +44,7 @@ else: address = None - kml.newpoint(name=title, coords=[(lon, lat)], address=address) + kml.newpoint(name=name, coords=[(lon, lat)], address=address) count += 1 print(f'Saving file "{outputFile}"') From c4e737250eea98ecc5f27087b0fdbcef5b002d99 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 13:09:49 -0400 Subject: [PATCH 09/12] kml.resetidcounter() Each new file was continuing the sequence from the last one (The Document ID is not affected, though. Still need to completely restart interpreter to make that repeatable from one KML to the next?) --- json2kml.py | 1 + 1 file changed, 1 insertion(+) diff --git a/json2kml.py b/json2kml.py index 34d7963..6bb672c 100644 --- a/json2kml.py +++ b/json2kml.py @@ -27,6 +27,7 @@ data = json.load(jsonFile) kml = simplekml.Kml() +kml.resetidcounter() kml.document.name = outputFile count = 0 From bfbe5902903f7b17bdb8e4d5a0eba31716497ab2 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 13:24:04 -0400 Subject: [PATCH 10/12] Add support for Labeled Places.json format Saved Places format: ```json {'geometry': {'coordinates': [...], 'type': 'Point'}, 'properties': {'Google Maps URL': '...', 'Location': {'Address': '...', 'Business Name': '...', 'Country Code': 'US', 'Geo Coordinates': {'Latitude': '...', 'Longitude': '...'}}, 'Published': '2018-05-02T01:46:02Z', 'Title': '...', 'Updated': '2018-05-02T01:46:02Z'}, 'type': 'Feature'} ``` Labeled Places format: ```json {'geometry': {'coordinates': [...], 'type': 'Point'}, 'properties': {'address': '...', 'name': 'Home'}, 'type': 'Feature'} ``` --- json2kml.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/json2kml.py b/json2kml.py index 6bb672c..fb8bd27 100644 --- a/json2kml.py +++ b/json2kml.py @@ -33,17 +33,28 @@ count = 0 for place in data["features"]: if place["type"] == "Feature": - name = html.escape(place["properties"]["Title"]) + try: + name = html.escape(place["properties"]["Title"]) + except KeyError: + name = html.escape(place["properties"]["name"]) print(f'Parsing place "{name}"') - placeLocation = place["properties"]["Location"] lon = place["geometry"]["coordinates"][0] lat = place["geometry"]["coordinates"][1] - if "Address" in placeLocation: - address = html.escape(placeLocation["Address"]) - else: - address = None + try: + placeLocation = place["properties"]["Location"] + + if "Address" in placeLocation: + address = html.escape(placeLocation["Address"]) + else: + address = None + + except KeyError: + if 'address' in place['properties']: + address = html.escape(place['properties']['address']) + else: + address = None kml.newpoint(name=name, coords=[(lon, lat)], address=address) count += 1 From f49c4903c2d81099ad63c75fe12f261815fb1211 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 23 Oct 2022 13:33:29 -0400 Subject: [PATCH 11/12] Use sys.argv instead of hardcoded filename So you can it from the command line --- json2kml.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/json2kml.py b/json2kml.py index fb8bd27..1f30c0b 100644 --- a/json2kml.py +++ b/json2kml.py @@ -14,7 +14,12 @@ import codecs import html -inputFile = "Saved Places.json" +try: + inputFile = sys.argv[1] +except IndexError: + print("Usage: python json2kml.py filename.json") + exit(1) + outputFile = f'{inputFile[:-5]} [json2kml.py].kml' # JSON Encoding is UTF-8. Change stdout to UTF-8 to prevent encoding error From ebe8f843c622187af8023cd6a775ae9b5f25fe65 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 6 Nov 2022 22:19:44 -0500 Subject: [PATCH 12/12] Names are already URL-encoded, just not addresses? Actually neither is true of original .json file. This must be a Python simplekml issue? Names are already encoded but addresses are not? --- json2kml.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/json2kml.py b/json2kml.py index 1f30c0b..f0262f0 100644 --- a/json2kml.py +++ b/json2kml.py @@ -39,9 +39,9 @@ for place in data["features"]: if place["type"] == "Feature": try: - name = html.escape(place["properties"]["Title"]) + name = place["properties"]["Title"] except KeyError: - name = html.escape(place["properties"]["name"]) + name = place["properties"]["name"] print(f'Parsing place "{name}"') lon = place["geometry"]["coordinates"][0]