def deserialize(cls, did_doc: dict) -> 'DIDDoc':
        """
        Construct DIDDoc object from dict representation.

        Raise BadIdentifier for bad DID.

        :param did_doc: DIDDoc dict reprentation.
        :return: DIDDoc from input json.
        """

        rv = None
        if 'id' in did_doc:
            rv = DIDDoc(did_doc['id'])
        else:  # get DID to serve as DID document identifier from first public key
            if 'publicKey' not in did_doc:
                LOGGER.debug('DIDDoc.deserialize <!< no identifier in DID document')
                raise AbsentDIDDocItem('No identifier in DID document')
            for pubkey in did_doc['publicKey']:
                pubkey_did = canon_did(resource(pubkey['id']))
                if ok_did(pubkey_did):
                    rv = DIDDoc(pubkey_did)
                    break
            else:
                LOGGER.debug('DIDDoc.deserialize <!< no identifier in DID document')
                raise AbsentDIDDocItem('No identifier in DID document')

        for pubkey in did_doc['publicKey']:  # include public keys and authentication keys by reference
            pubkey_type = PublicKeyType.get(pubkey['type'])
            authn = any(
                canon_ref(rv.did, ak.get('publicKey', '')) == canon_ref(rv.did, pubkey['id'])
                for ak in did_doc.get('authentication', {}) if isinstance(ak.get('publicKey', None), str))
            key = PublicKey(  # initialization canonicalizes id
                rv.did,
                pubkey['id'],
                pubkey[pubkey_type.specifier],
                pubkey_type,
                canon_did(pubkey['controller']),
                authn)
            rv.pubkey[key.id] = key

        for akey in did_doc.get('authentication', {}):  # include embedded authentication keys
            pk_ref = akey.get('publicKey', None)
            if pk_ref:
                pass  # got it already with public keys
            else:
                pubkey_type = PublicKeyType.get(akey['type'])
                key = PublicKey(  # initialization canonicalized id
                    rv.did,
                    akey['id'],
                    akey[pubkey_type.specifier],
                    pubkey_type,
                    canon_did(akey['controller']),
                    True)
                rv.pubkey[key.id] = key

        for service in did_doc.get('service', {}):
            endpoint = service['serviceEndpoint']
            svc = Service(  # initialization canonicalizes id
                rv.did,
                service.get('id', canon_ref(rv.did, 'assigned-service-{}'.format(len(rv.service)), ';')),
                service['type'],
                rv.add_service_pubkeys(service, 'recipientKeys'),
                rv.add_service_pubkeys(service, ['mediatorKeys', 'routingKeys']),
                canon_ref(rv.did, endpoint, ';') if ';' in endpoint else endpoint,
                service.get('priority', None))
            rv.service[svc.id] = svc

        return rv
Construct DIDDoc object from dict representation.

        Raise BadIdentifier for bad DID.

        :param did_doc: DIDDoc dict reprentation.
        :return: DIDDoc from input json.