Signatur
Beschreibung
toJSON() ist der Standard-Serialisierer von PushSubscription. Die Methode liefert ein einfaches, JSON-fähiges Objekt mit allen Angaben, die ein Anwendungsserver zum Versand von Web-Push-Nachrichten braucht: die endpoint-URL des Push-Dienstes, die optionale expirationTime und das Objekt keys mit dem öffentlichen ECDH-Schlüssel p256dh und dem Authentifizierungsgeheimnis auth.
Der größte Vorteil: Die Schlüssel liegen bereits als Base64url-codierte Zeichenketten vor. Ohne toJSON() müsste man subscription.getKey('p256dh') und getKey('auth') aufrufen und die zurückgegebenen ArrayBuffer selbst codieren.
Da JSON.stringify() toJSON() automatisch aufruft, reicht in der Praxis oft JSON.stringify(subscription), zum Beispiel direkt im body eines fetch()-Aufrufs. Der direkte Aufruf lohnt sich, wenn man mit einzelnen Feldern arbeiten will, etwa um nur keys.auth zu speichern oder das Objekt vor dem Versand um eigene Daten zu erweitern.
Rückgabewert
Ein einfaches Objekt der Form { endpoint: string, expirationTime: number | null, keys: { p256dh: string, auth: string } }. Die Schlüssel sind Base64url-codiert, ohne Auffüllzeichen (=).
Beispiele
Abonnement abschließen und an den Server senden
// VAPID-Schlüssel (Base64url) in Uint8Array umwandeln
const urlBase64ToUint8Array = (base64) => {
const padding = '='.repeat((4 - (base64.length % 4)) % 4);
const raw = atob((base64 + padding).replace(/-/g, '+').replace(/_/g, '/'));
return Uint8Array.from(raw, (c) => c.charCodeAt(0));
};
const subscribeUser = async (vapidPublicKey) => {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey)
});
const data = subscription.toJSON();
console.log(data.endpoint);
await fetch('/api/push/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
};
Einzelne Felder auslesen und erweitern
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
const { endpoint, expirationTime, keys } = subscription.toJSON();
console.log('Läuft ab:', expirationTime ?? 'nie');
console.log('auth-Länge:', keys.auth.length);
// Eigene Metadaten ergänzen
const payload = { endpoint, keys, userId: 42, locale: navigator.language };
console.log(JSON.stringify(payload, null, 2));
}
Implizit über JSON.stringify()
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
// JSON.stringify ruft toJSON() automatisch auf
const a = JSON.stringify(subscription);
const b = JSON.stringify(subscription.toJSON());
console.log(a === b);
// Wichtig · Fallstricke
- Nicht mit dem Original verwechseln: Das Ergebnis ist ein totes Datenobjekt. Methoden wie
unsubscribe()odergetKey()gibt es darauf nicht. Verwende dafür weiterhin diePushSubscription-Instanz. - Kodierung:
p256dhundauthsind Base64url-codiert (-und_, ohne=). Serverbibliotheken wieweb-pushfür Node.js erwarten genau dieses Format.atob()kann sie ohne vorherige Umwandlung nicht decodieren. - Sicherheit:
endpointundauthgelten als Geheimnisse. Wer sie kennt, kann in Verbindung mit dem VAPID-Schlüssel Nachrichten an den Nutzer senden. Übertrage sie nur über HTTPS, speichere sie serverseitig geschützt und gib sie nicht in Protokollen aus. expirationTimeist in den meisten Browsernnull. Verlass dich nicht darauf. Reagiere stattdessen im Service Worker auf das Ereignispushsubscriptionchangeund behandle die Serverantworten 404/410 beim Versand.- Kompatibilität: Die Push-API gibt es nur in sicheren Kontexten (HTTPS) und nur mit einem registrierten Service Worker. Auf iOS/iPadOS funktioniert sie erst ab 16.4 und nur für Web-Apps, die zum Home-Bildschirm hinzugefügt wurden.