Gayatri Devi Vasudev
“The digital avatars of Jyotisha powered by Astro-Vision have spread awareness and are ideal to today's fast paced life...”
Converting between JSON and VCF is a common task when migrating contact data between web applications (which often use JSON) and legacy or mobile systems (which rely on VCF). This guide covers both directions of conversion, including specifications, code examples, edge cases, and tooling. 2.1 The VCF (vCard) Format A simple vCard 4.0 example:
# Structured name: N:last;first;middle;prefix;suffix n_parts = [ contact.get('lastName', ''), contact.get('firstName', ''), contact.get('middleName', ''), contact.get('prefix', ''), contact.get('suffix', '') ] lines.append(f"N:';'.join(n_parts)")
# Phones with types for phone in contact.get('phone', []): ptype = phone.get('type', '').upper() if ptype: lines.append(f"TEL;TYPE=ptype:phone['number']") else: lines.append(f"TEL:phone['number']")
lines.append("END:VCARD") return "\n".join(lines) with open('contacts.json') as f: contacts = json.load(f)
with open(vcf_file_path, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if not line: continue if line == "BEGIN:VCARD": current_contact = {} elif line == "END:VCARD": if current_contact: contacts.append(current_contact) current_contact = None else: prop, value, params = parse_vcf_line(line) if prop == "VERSION": current_contact['version'] = value elif prop == "FN": current_contact['fullName'] = value elif prop == "N": # N:last;first;middle;prefix;suffix parts = value.split(';') current_contact['lastName'] = parts[0] current_contact['firstName'] = parts[1] if len(parts) > 1 else '' current_contact['middleName'] = parts[2] if len(parts) > 2 else '' current_contact['prefix'] = parts[3] if len(parts) > 3 else '' current_contact['suffix'] = parts[4] if len(parts) > 4 else '' elif prop == "EMAIL": if 'email' not in current_contact: current_contact['email'] = [] current_contact['email'].append(value) elif prop == "TEL": if 'phone' not in current_contact: current_contact['phone'] = [] phone_entry = 'number': value if 'type' in params: phone_entry['type'] = params['type'] current_contact['phone'].append(phone_entry) elif prop == "ADR": # ADR: ;street;city;region;code;country parts = value.split(';') # Typically parts[0] = PO box, parts[1] = extended, parts[2] = street, etc. if len(parts) >= 6: current_contact['address'] = 'street': parts[2], 'city': parts[3], 'region': parts[4], 'code': parts[5], 'country': parts[6] if len(parts) > 6 else '' elif prop == "ORG": current_contact['organization'] = value return contacts contacts_json = vcf_to_json('input.vcf') with open('output.json', 'w') as f: json.dump(contacts_json, f, indent=2) 5. Handling Complex vCard Features 5.1 Groups and Multiple Entries vCard supports grouping (e.g., item1.EMAIL;TYPE=work ). A robust converter must parse the group prefix and reconstruct it in JSON, usually as nested objects. 5.2 Binary Data (Photos/Logos) vCard can embed base64-encoded images ( PHOTO;ENCODING=b;TYPE=JPEG:... ). Convert to JSON as a base64 string and optionally decode to a URL or file reference. 5.3 Custom Properties (X- extensions) Properties like X-ABUID (Apple Address Book UID) should be preserved in JSON under a custom or x-properties object. 5.4 Multi-line Values (Folded Lines) vCard 3.0 uses folding: a line starting with a space or tab continues the previous property. A parser must unfold these before processing.
# Organization if 'organization' in contact: lines.append(f"ORG:contact['organization']")
Converting between JSON and VCF is a common task when migrating contact data between web applications (which often use JSON) and legacy or mobile systems (which rely on VCF). This guide covers both directions of conversion, including specifications, code examples, edge cases, and tooling. 2.1 The VCF (vCard) Format A simple vCard 4.0 example:
# Structured name: N:last;first;middle;prefix;suffix n_parts = [ contact.get('lastName', ''), contact.get('firstName', ''), contact.get('middleName', ''), contact.get('prefix', ''), contact.get('suffix', '') ] lines.append(f"N:';'.join(n_parts)") json vcf 変換
# Phones with types for phone in contact.get('phone', []): ptype = phone.get('type', '').upper() if ptype: lines.append(f"TEL;TYPE=ptype:phone['number']") else: lines.append(f"TEL:phone['number']") Converting between JSON and VCF is a common
lines.append("END:VCARD") return "\n".join(lines) with open('contacts.json') as f: contacts = json.load(f) if len(parts) >
with open(vcf_file_path, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if not line: continue if line == "BEGIN:VCARD": current_contact = {} elif line == "END:VCARD": if current_contact: contacts.append(current_contact) current_contact = None else: prop, value, params = parse_vcf_line(line) if prop == "VERSION": current_contact['version'] = value elif prop == "FN": current_contact['fullName'] = value elif prop == "N": # N:last;first;middle;prefix;suffix parts = value.split(';') current_contact['lastName'] = parts[0] current_contact['firstName'] = parts[1] if len(parts) > 1 else '' current_contact['middleName'] = parts[2] if len(parts) > 2 else '' current_contact['prefix'] = parts[3] if len(parts) > 3 else '' current_contact['suffix'] = parts[4] if len(parts) > 4 else '' elif prop == "EMAIL": if 'email' not in current_contact: current_contact['email'] = [] current_contact['email'].append(value) elif prop == "TEL": if 'phone' not in current_contact: current_contact['phone'] = [] phone_entry = 'number': value if 'type' in params: phone_entry['type'] = params['type'] current_contact['phone'].append(phone_entry) elif prop == "ADR": # ADR: ;street;city;region;code;country parts = value.split(';') # Typically parts[0] = PO box, parts[1] = extended, parts[2] = street, etc. if len(parts) >= 6: current_contact['address'] = 'street': parts[2], 'city': parts[3], 'region': parts[4], 'code': parts[5], 'country': parts[6] if len(parts) > 6 else '' elif prop == "ORG": current_contact['organization'] = value return contacts contacts_json = vcf_to_json('input.vcf') with open('output.json', 'w') as f: json.dump(contacts_json, f, indent=2) 5. Handling Complex vCard Features 5.1 Groups and Multiple Entries vCard supports grouping (e.g., item1.EMAIL;TYPE=work ). A robust converter must parse the group prefix and reconstruct it in JSON, usually as nested objects. 5.2 Binary Data (Photos/Logos) vCard can embed base64-encoded images ( PHOTO;ENCODING=b;TYPE=JPEG:... ). Convert to JSON as a base64 string and optionally decode to a URL or file reference. 5.3 Custom Properties (X- extensions) Properties like X-ABUID (Apple Address Book UID) should be preserved in JSON under a custom or x-properties object. 5.4 Multi-line Values (Folded Lines) vCard 3.0 uses folding: a line starting with a space or tab continues the previous property. A parser must unfold these before processing.
# Organization if 'organization' in contact: lines.append(f"ORG:contact['organization']")