Last active
November 7, 2025 13:23
-
-
Save noogen/ebec999e1652ca93029d49f462135f7d to your computer and use it in GitHub Desktop.
Transform PasswordBoss JSON export to Safari CSV Export for import into StickyPassword
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import json | |
| def transformPasswordBossToSafariExport(json_file_path, text_file_path): | |
| """ | |
| Opens a PasswordBoss JSON file, iterates through its contents, and appends | |
| CSV data to a text file. | |
| Since Safari Password is widely use by Mac Users, it is supported by StickyPassword | |
| and other Password Management System. It allow us to import Safari Password | |
| and/or other Password Management System. | |
| The data also get sorted first so it make it easy for us to do a compare of files | |
| to get the diff or changes. | |
| Args: | |
| json_file_path (str): The path to the input JSON file. | |
| text_file_path (str): The path to the output text file. | |
| """ | |
| try: | |
| with open(json_file_path, 'r', encoding='utf-8') as json_file: | |
| obj = json.load(json_file) | |
| data = obj['items'] | |
| with open(text_file_path, 'w', encoding='utf-8') as text_file: | |
| text_file.write("Title,URL,Username,Password,Notes,OTPAuth") # Separator for clarity | |
| # Assuming 'data' is a list of dictionaries, iterate through each item | |
| if isinstance(data, list): | |
| data.sort(key=lambda x: x["name"]) | |
| for item in data: | |
| if 'identifiers' in item: | |
| id = item['identifiers'] | |
| if 'username' in id: | |
| text_file.write(f"\npb-{item['name']}") | |
| if 'login_url' in item: | |
| text_file.write(f",{item['login_url']}") | |
| elif 'url' in id: | |
| text_file.write(f",{id['url']}") | |
| else: | |
| text_file.write(",") | |
| if 'username' in id: | |
| text_file.write(f",{id['username']}") | |
| else: | |
| text_file.write(",") | |
| if 'password' in id: | |
| text_file.write(f",{id['password']}") | |
| else: | |
| text_file.write(",") | |
| if 'notes' in id: | |
| text_file.write(f",{id['notes'].replace("\n", "|")}") | |
| else: | |
| text_file.write(",") | |
| text_file.write(",") | |
| print(f"Data from '{json_file_path}' successfully appended to '{text_file_path}'.") | |
| except FileNotFoundError: | |
| print(f"Error: One of the files '{json_file_path}' or '{text_file_path}' not found.") | |
| except json.JSONDecodeError: | |
| print(f"Error: Could not decode JSON from '{json_file_path}'. Check file format.") | |
| except Exception as e: | |
| print(f"An unexpected error occurred: {e}") | |
| # Call the function with your file paths | |
| transformPasswordBossToSafariExport('PasswordBossExport.json', 'SafariPasswordExport.csv') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment