Function to parse vCard into JSON elements

I have users contact info saved as a vCard within a JSON object. I’d like to access this and extract the elements (Name, Tel, Email etc) into JSON elements to that I can access/reference them individually within n8n.

I’ve found a few resources online to support with this - like this npm library (https://www.npmjs.com/package/vcard) and whilst I read that it is possible to use external libraries with n8n - I’m not sure if it is whilst hosting my instance on n8n Cloud.

Would love to hear from other n8n user who either know how to do this, or have accomplished something similar via any means that could sit in n8n.

Below is an example of a typical vCard:

BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iPhone OS 15.1//EN
N:Bucket;Sam;;;
FN:Sam Bucket
TEL;type=CELL;type=VOICE;type=pref:+14183838117
item1.TEL:+1201649394
item1.X-ABLabel:InReach
item2.TEL:+881632722637
item2.X-ABLabel:Sat Phone
ADR;type=HOME;type=pref:;;Kings Beach;California;96188;United States
item3.URL;type=pref:www.url.org
item3.X-ABLabel:$!!$
BDAY:1979-01-03
item4.IMPP;X-SERVICE-TYPE=Facebook;type=pref:xmpp:username
item4.X-ABLabel:Facebook
END:VCARD

Hi @Felix_is_stuck, this sounds like quite a challenge to build yourself without a designated node. Luckily, this problem has already been solved, for example here:

You could for example use such parser code in a Function node. Here is an example using the above parser and then reading the full name (which just takes the first value from the FN field) as well as the home address (which performs a bit of filtering for demo purposes):

Example Workflow

Hope this helps! Let me know if you run into any trouble here.

Wow. You are my hero.

I tried to adapt the code to output an Email variable (if it’s present) but I’m clearly doing it wrong as it failed.

for (item of items) {
    const parsed = parse(item.json.VCard);
    item.json.full_name = parsed.fn[0].value;
    item.json.email = parsed.email[0].value;
    item.json.home_address = parsed.adr
        .find(e => e.meta.type.includes('HOME')).value
        .filter(e => e)
        .join(', ');
}

The function as pasted from your example above is also failing if I pass a different vCard to it - one that doesn’t have a ‘Home Address’ set, is that the expected behavior?

Ideally it would output all of the variables stored in the vCard, and only if they are present.

Ah, I didn’t add any checks as to whether the respective element exists in my example code. So when trying to extract a non-existing field, you’d indeed get an error (probably something like Cannot read property '0' of undefined).

I don’t know much about vcards and all the different formats they could have, but have added some checks using the ternary operator in the below example:

for (item of items) {
    const parsed = parse(item.json.vcard);
    console.log(parsed);
    item.json.full_name = parsed.fn && parsed.fn.length > 0 ? parsed.fn[0].value : null;
    item.json.home_address = parsed.adr && parsed.adr.find(e => e.meta.type.includes('HOME')) ? parsed.adr
        .find(e => e.meta.type.includes('HOME')).value
        .filter(e => e)
        .join(', ') : null;
    item.json.email = parsed.email && parsed.email.length > 0 ? parsed.email[0].value : null;
}

return items;

This would simply leave non-existent field empty instead of throwing an error:

I have also added console.log(parsed); to the example snippet above, so you can easily inspect the parsed data in your browser console:
image

Thank you!!

1 Like