Framework
Version
Integrationen

Benutzerdefinierte Serialisierung von Suchparametern

Standardmäßig parst und serialisiert TanStack Router Ihre URL-Suchparameter automatisch mit JSON.stringify und JSON.parse. Dieser Prozess beinhaltet das Escapen und Unescapen des Suchstrings, was eine gängige Praxis für URL-Suchparameter ist, zusätzlich zur Serialisierung und Deserialisierung des Suchobjekts.

Zum Beispiel, bei Verwendung der Standardkonfiguration, wenn Sie folgendes Suchobjekt haben

tsx
const search = {
  page: 1,
  sort: 'asc',
  filters: { author: 'tanner', min_words: 800 },
}
const search = {
  page: 1,
  sort: 'asc',
  filters: { author: 'tanner', min_words: 800 },
}

Es würde in den folgenden Suchstring serialisiert und escaped werden

txt
?page=1&sort=asc&filters=%7B%22author%22%3A%22tanner%22%2C%22min_words%22%3A800%7D
?page=1&sort=asc&filters=%7B%22author%22%3A%22tanner%22%2C%22min_words%22%3A800%7D

Wir können das Standardverhalten mit dem folgenden Code implementieren

tsx
import {
  createRouter,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'

const router = createRouter({
  // ...
  parseSearch: parseSearchWith(JSON.parse),
  stringifySearch: stringifySearchWith(JSON.stringify),
})
import {
  createRouter,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'

const router = createRouter({
  // ...
  parseSearch: parseSearchWith(JSON.parse),
  stringifySearch: stringifySearchWith(JSON.stringify),
})

Dieses Standardverhalten ist jedoch möglicherweise nicht für alle Anwendungsfälle geeignet. Zum Beispiel möchten Sie möglicherweise ein anderes Serialisierungsformat verwenden, wie z. B. Base64-Codierung, oder Sie möchten eine speziell entwickelte Serialisierungs-/Deserialisierungsbibliothek verwenden, wie z. B. query-string, JSURL2 oder Zipson.

Dies kann erreicht werden, indem Sie Ihre eigenen Serialisierungs- und Deserialisierungsfunktionen für die Optionen parseSearch und stringifySearch in der Router-Konfiguration bereitstellen. Dabei können Sie die integrierten Hilfsfunktionen von TanStack Router, parseSearchWith und stringifySearchWith, nutzen, um den Prozess zu vereinfachen.

Tipp

Ein wichtiger Aspekt der Serialisierung und Deserialisierung ist, dass Sie nach der Deserialisierung dasselbe Objekt zurückerhalten können. Dies ist wichtig, da Sie Informationen verlieren können, wenn der Serialisierungs- und Deserialisierungsprozess nicht korrekt durchgeführt wird. Wenn Sie beispielsweise eine Bibliothek verwenden, die keine verschachtelten Objekte unterstützt, verlieren Sie das verschachtelte Objekt bei der Deserialisierung des Suchstrings.

Diagram showing idempotent nature of URL search param serialization and deserialization

Hier sind einige Beispiele, wie Sie die Serialisierung von Suchparametern in TanStack Router anpassen können

Verwendung von Base64

Es ist üblich, Ihre Suchparameter Base64-codiert zu kodieren, um maximale Kompatibilität mit Browsern und URL-Unfurdern usw. zu erreichen. Dies kann mit dem folgenden Code erfolgen

tsx
import {
  Router,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'

const router = createRouter({
  parseSearch: parseSearchWith((value) => JSON.parse(decodeFromBinary(value))),
  stringifySearch: stringifySearchWith((value) =>
    encodeToBinary(JSON.stringify(value)),
  ),
})

function decodeFromBinary(str: string): string {
  return decodeURIComponent(
    Array.prototype.map
      .call(atob(str), function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join(''),
  )
}

function encodeToBinary(str: string): string {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
      return String.fromCharCode(parseInt(p1, 16))
    }),
  )
}
import {
  Router,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'

const router = createRouter({
  parseSearch: parseSearchWith((value) => JSON.parse(decodeFromBinary(value))),
  stringifySearch: stringifySearchWith((value) =>
    encodeToBinary(JSON.stringify(value)),
  ),
})

function decodeFromBinary(str: string): string {
  return decodeURIComponent(
    Array.prototype.map
      .call(atob(str), function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join(''),
  )
}

function encodeToBinary(str: string): string {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
      return String.fromCharCode(parseInt(p1, 16))
    }),
  )
}

⚠️ Warum verwendet dieser Schnipsel nicht atob/btoa?

Wenn wir das vorherige Objekt mit dieser Konfiguration in einen Suchstring umwandeln würden, sähe es so aus

txt
?page=1&sort=asc&filters=eyJhdXRob3IiOiJ0YW5uZXIiLCJtaW5fd29yZHMiOjgwMH0%3D
?page=1&sort=asc&filters=eyJhdXRob3IiOiJ0YW5uZXIiLCJtaW5fd29yZHMiOjgwMH0%3D

Warnung

Wenn Sie Benutzereingaben in Base64 serialisieren, riskieren Sie eine Kollision mit der URL-Deserialisierung. Dies kann zu unerwartetem Verhalten führen, z. B. dass die URL nicht korrekt geparst wird oder als anderer Wert interpretiert wird. Um dies zu vermeiden, sollten Sie die Suchparameter mit einer sicheren Binärcodierungs/-decodierungsmethode (siehe unten) kodieren.

Verwendung der query-string-Bibliothek

Die query-string-Bibliothek ist beliebt dafür, Query-Strings zuverlässig parsen und stringifizieren zu können. Sie können sie verwenden, um das Serialisierungsformat Ihrer Suchparameter anzupassen. Dies kann mit dem folgenden Code erfolgen

tsx
import { createRouter } from '@tanstack/react-router'
import qs from 'query-string'

const router = createRouter({
  // ...
  stringifySearch: stringifySearchWith((value) =>
    qs.stringify(value, {
      // ...options
    }),
  ),
  parseSearch: parseSearchWith((value) =>
    qs.parse(value, {
      // ...options
    }),
  ),
})
import { createRouter } from '@tanstack/react-router'
import qs from 'query-string'

const router = createRouter({
  // ...
  stringifySearch: stringifySearchWith((value) =>
    qs.stringify(value, {
      // ...options
    }),
  ),
  parseSearch: parseSearchWith((value) =>
    qs.parse(value, {
      // ...options
    }),
  ),
})

Wenn wir das vorherige Objekt mit dieser Konfiguration in einen Suchstring umwandeln würden, sähe es so aus

txt
?page=1&sort=asc&filters=author%3Dtanner%26min_words%3D800
?page=1&sort=asc&filters=author%3Dtanner%26min_words%3D800

Verwendung der JSURL2-Bibliothek

JSURL2 ist eine nicht standardisierte Bibliothek, die URLs komprimieren kann und dabei lesbar bleibt. Dies kann mit dem folgenden Code erfolgen

tsx
import {
  Router,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'
import { parse, stringify } from 'jsurl2'

const router = createRouter({
  // ...
  parseSearch: parseSearchWith(parse),
  stringifySearch: stringifySearchWith(stringify),
})
import {
  Router,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'
import { parse, stringify } from 'jsurl2'

const router = createRouter({
  // ...
  parseSearch: parseSearchWith(parse),
  stringifySearch: stringifySearchWith(stringify),
})

Wenn wir das vorherige Objekt mit dieser Konfiguration in einen Suchstring umwandeln würden, sähe es so aus

txt
?page=1&sort=asc&filters=(author~tanner~min*_words~800)~
?page=1&sort=asc&filters=(author~tanner~min*_words~800)~

Verwendung der Zipson-Bibliothek

Zipson ist eine sehr benutzerfreundliche und performante JSON-Komprimierungsbibliothek (sowohl in Bezug auf die Laufzeit-Performance als auch auf die resultierende Komprimierungs-Performance). Um Ihre Suchparameter damit zu komprimieren (was auch das Escapen/Unescapen und Base64-Codieren/Decodieren erfordert), können Sie den folgenden Code verwenden

tsx
import {
  Router,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'
import { stringify, parse } from 'zipson'

const router = createRouter({
  parseSearch: parseSearchWith((value) => parse(decodeFromBinary(value))),
  stringifySearch: stringifySearchWith((value) =>
    encodeToBinary(stringify(value)),
  ),
})

function decodeFromBinary(str: string): string {
  return decodeURIComponent(
    Array.prototype.map
      .call(atob(str), function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join(''),
  )
}

function encodeToBinary(str: string): string {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
      return String.fromCharCode(parseInt(p1, 16))
    }),
  )
}
import {
  Router,
  parseSearchWith,
  stringifySearchWith,
} from '@tanstack/react-router'
import { stringify, parse } from 'zipson'

const router = createRouter({
  parseSearch: parseSearchWith((value) => parse(decodeFromBinary(value))),
  stringifySearch: stringifySearchWith((value) =>
    encodeToBinary(stringify(value)),
  ),
})

function decodeFromBinary(str: string): string {
  return decodeURIComponent(
    Array.prototype.map
      .call(atob(str), function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join(''),
  )
}

function encodeToBinary(str: string): string {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
      return String.fromCharCode(parseInt(p1, 16))
    }),
  )
}

⚠️ Warum verwendet dieser Schnipsel nicht atob/btoa?

Wenn wir das vorherige Objekt mit dieser Konfiguration in einen Suchstring umwandeln würden, sähe es so aus

txt
?page=1&sort=asc&filters=JTdCJUMyJUE4YXV0aG9yJUMyJUE4JUMyJUE4dGFubmVyJUMyJUE4JUMyJUE4bWluX3dvcmRzJUMyJUE4JUMyJUEyQ3UlN0Q%3D
?page=1&sort=asc&filters=JTdCJUMyJUE4YXV0aG9yJUMyJUE4JUMyJUE4dGFubmVyJUMyJUE4JUMyJUE4bWluX3dvcmRzJUMyJUE4JUMyJUEyQ3UlN0Q%3D

Sichere Binärcodierung/-decodierung

Im Browser wird nicht garantiert, dass die Funktionen atob und btoa mit Nicht-UTF8-Zeichen korrekt funktionieren. Wir empfehlen stattdessen die Verwendung dieser Codierungs-/Decodierungs-Hilfsprogramme

Zum Kodieren von einem String zu einem Binärstring

typescript
export function encodeToBinary(str: string): string {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
      return String.fromCharCode(parseInt(p1, 16))
    }),
  )
}
export function encodeToBinary(str: string): string {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
      return String.fromCharCode(parseInt(p1, 16))
    }),
  )
}

Zum Dekodieren von einem Binärstring zu einem String

typescript
export function decodeFromBinary(str: string): string {
  return decodeURIComponent(
    Array.prototype.map
      .call(atob(str), function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join(''),
  )
}
export function decodeFromBinary(str: string): string {
  return decodeURIComponent(
    Array.prototype.map
      .call(atob(str), function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join(''),
  )
}
Unsere Partner
Code Rabbit
Netlify
Neon
Clerk
Convex
Sentry
Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.

Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.