protected function convertVCard($data, $target, array $propertiesFilter = null)
    {
        if (is_resource($data)) {
            $data = stream_get_contents($data);
        }
        $input = VObject\Reader::read($data);
        if (!empty($propertiesFilter)) {
            $propertiesFilter = array_merge(['UID', 'VERSION', 'FN'], $propertiesFilter);
            $keys = array_unique(array_map(function ($child) {
                return $child->name;
            }, $input->children()));
            $keys = array_diff($keys, $propertiesFilter);
            foreach ($keys as $key) {
                unset($input->$key);
            }
            $data = $input->serialize();
        }
        $output = null;
        try {
            switch ($target) {
                default:
                case 'vcard3':
                    if (VObject\Document::VCARD30 === $input->getDocumentType()) {
                        // Do nothing
                        return $data;
                    }
                    $output = $input->convert(VObject\Document::VCARD30);

                    return $output->serialize();
                case 'vcard4':
                    if (VObject\Document::VCARD40 === $input->getDocumentType()) {
                        // Do nothing
                        return $data;
                    }
                    $output = $input->convert(VObject\Document::VCARD40);

                    return $output->serialize();
                case 'jcard':
                    $output = $input->convert(VObject\Document::VCARD40);

                    return json_encode($output);
            }
        } finally {
            // Destroy circular references to PHP will GC the object.
            $input->destroy();
            if (!is_null($output)) {
                $output->destroy();
            }
        }
    }