Deeplinks mit übereinstimmenden URIs

Verwenden Sie, um hierarchische URIs mit Mustern abzugleichen und Argumente zu extrahieren UriDeepLinkMatcher. Dabei wird kotlinx.serialization verwendet, um übereinstimmende Argumente in Ihre Schlüsselklassen zu deserialisieren.

Um einen UriDeepLinkMatcher zu erstellen, geben Sie ein DeepLinkUri-Muster und den Serializer für den entsprechenden Schlüssel an:

Informationen zu nicht hierarchischen URIs oder benutzerdefinierten Schemas (z. B. tel:) finden Sie unter Benutzerdefinierte Matcher für Deeplinks erstellen.

Unterstützte Abgleichsmuster

UriDeepLinkMatcher gleicht URIs anhand ihrer fünf Komponenten ab: Schema, Authority, Pfad, Abfrage und Fragment. In den folgenden Abschnitten werden die unterstützte Mustersyntax, Argumentplatzhalter und Abgleichsregeln für jede Komponente beschrieben.

Schemaabgleich

Wenn im URI-Muster kein Schema vorhanden ist, werden sowohl http als auch https abgeglichen. Wenn Sie ein bestimmtes Schema abgleichen möchten, fügen Sie es in das Muster ein. Ausnahmsweise gleicht ein http Schema in einem Muster sowohl http als auch https Anfrage-URIs ab, während https in einem Muster nur https Anfragen abgleicht.

Muster-URI Anfrage-URI Übereinstimmung
www.example.com https://www.example.com
www.example.com http://www.example.com
http://www.example.com http://www.example.com
http://www.example.com https://www.example.com
https://www.example.com http://www.example.com
myapp://www.example.com myapp://www.example.com

Authority-Abgleich

UriDeepLinkMatcher führt einen genauen Abgleich ohne Berücksichtigung der Groß- und Kleinschreibung für die URI-Authority (Host und optionaler Port) durch. Platzhalter oder Wildcards werden in der Authority nicht unterstützt und es werden keine Argumente extrahiert:

Muster-URI Anfrage-URI Übereinstimmung
example.com https://example.com
example.com https://EXAMPLE.COM
example.com https://sub.example.com
example.com https://www.example.com
example.com https://example.com:8080
example.com:8080 https://example.com:8080
example.com:8080 https://example.com

Pfadabgleich

Die folgenden Pfadmuster werden unterstützt:

Muster-URI Anfrage-URI Übereinstimmung Extrahierte Argumente
www.example.com/users https://www.example.com/users Keine
www.example.com/users/{id} https://www.example.com/users/123 id: "123"
www.example.com/users/{first}-{last} https://www.example.com/users/john-doe first: "john", last: "doe"
www.example.com/users/{id}/profile https://www.example.com/users//profile id: "" (leerer String)
www.example.com/users/user_{id} https://www.example.com/users/user_123 id: "123"
www.example.com/users/{userId}/posts/{postId} https://www.example.com/users/123/posts/456 userId: "123", postId: "456"
www.example.com/users/.* https://www.example.com/users/john-doe Keine
www.example.com/users https://www.example.com/users/ ❌ (Der nachgestellte Schrägstrich erstellt ein zusätzliches Segment)

Abfrageabgleich

Die Reihenfolge der Abfrageparameter in der Anfrage-URI muss nicht mit der Reihenfolge in der Muster-URI übereinstimmen. Außerdem werden Parameter, die in der Anfrage-URI, aber nicht in der Muster-URI vorhanden sind, ignoriert.

Die folgenden Muster für Abfrageparameter werden unterstützt:

Muster-URI Anfrage-URI Extrahierte Argumente
www.example.com/users?name={name} https://www.example.com/users?name=john name: "john"
www.example.com/users?name={name} https://www.example.com/users?name= name: "" (leerer String)
www.example.com/users?{rawQuery} https://www.example.com/users?anything&else rawQuery: ["anything", "else"]
www.example.com/users?type=user_{id} https://www.example.com/users?type=user_123 id: "123"
www.example.com/users?name={first}_{last} https://www.example.com/users?name=john_doe first: "john", last: "doe"
www.example.com/users?list={list} https://www.example.com/users?list=10&list=20 list: ["10", "20"]
www.example.com/users?name={name}&{other} https://www.example.com/users?name=john&tab=info name: "john", other: ["tab=info"]
www.example.com/users?type=user_.* https://www.example.com/users?type=user_admin type: "admin"

Fragmentabgleich

Die folgenden Fragmentmustertypen werden unterstützt:

Muster-URI Anfrage-URI Extrahierte Argumente
www.example.com/#section1 https://www.example.com/#section1 Keine
www.example.com/#section_{id} https://www.example.com/#section_123 id: "123"
www.example.com/#section_.* https://www.example.com/#section_123 Keine

Unterstützte Datentypen

UriDeepLinkMatcher unterstützt die Deserialisierung von URI-Argumenten in primitive Typen, Enums, Sammlungen und benutzerdefinierte Objekte. Die Serialisierung lässt sich in zwei Kategorien unterteilen:

  • Standardserialisierung: Verwendet kotlinx.serialization für die Deserialisierung in:
    • Primitive Typen (Boolean, Int, Long, Float, Double, Char, Byte, Short) und String
    • Enums
    • Set, List oder Array von primitiven Typen, Strings oder Enums
    • Verschachtelte @Serializable-Klassen (deren Attribute in einzelne URI-Platzhalter umgewandelt werden)
  • Benutzerdefinierte Serialisierung mit DeepLinkSerializer: Konvertiert zwischen einem einzelnen String und benutzerdefinierten Objekten, externen Typen (z. B. java.time.LocalDate) oder benutzerdefinierten Sammlungen.

Standardserialisierung

UriDeepLinkMatcher funktioniert sofort für Standardtypen und umgewandelte Strukturen, ohne dass benutzerdefinierte Serialisierungsimplementierungen erforderlich sind.

Primitive Typen und Strings

UriDeepLinkMatcher decodiert automatisch primitive Typen (Boolean, Int, Long, Float, Double, Char, Byte, Short) und String:

Enums

Enum-Werte werden ohne Berücksichtigung der Groß- und Kleinschreibung mit den Namen der Enum-Elemente abgeglichen:

Wiederholte Abfragesammlungen

Abfrageparameter mit wiederholten Schlüsseln (z. B. ?id=10&id=20) werden automatisch in List<T>, Set<T>, oder Array<T> deserialisiert, wobei T ein primitiver Typ, String, oder Enum ist:

Verschachtelte @Serializable-Klassen

Wenn ein NavKey ein Attribut enthält, dessen Typ eine andere @Serializable-Klasse ist, wandelt UriDeepLinkMatcher die Attribute um, sodass jedes Attribut der verschachtelten Klasse direkt einem einzelnen URI-Parameter mit demselben Namen zugeordnet wird:

Wenn Sie benutzerdefinierte Objekte (z. B. Filter(key = "brand", value = "pixel")), externe Typen (z. B. java.time.LocalDate) oder benutzerdefinierte Strings (z. B. durch Kommas getrennte Werte) deserialisieren möchten, erweitern Sie DeepLinkSerializer<T>.

DeepLinkSerializer<T> ist ein abstrakter KSerializer<T>, der zwischen einem String und T konvertiert:

abstract class DeepLinkSerializer<T : Any> : KSerializer<T> {
    abstract val serialName: String
    abstract fun deserialize(value: String): T
    abstract fun serialize(value: T): String
}

Betrachten Sie beispielsweise die Filter und FilterSerializer Definitionen, die in den folgenden Snippets verwendet werden:

Einzelne benutzerdefinierte Objekte

Wenn Sie ein Objekt aus einem einzelnen URI-Parameterstring decodieren möchten (z. B. ?filter=brand:google), versehen Sie das Attribut mit @Serializable(with = ...):

Benutzerdefinierte Objekte in wiederholten Abfrageparametern

Wenn Sie wiederholte Abfrageparameter in eine Sammlung benutzerdefinierter Objekte (List<T>, Set<T>, oder Array<T>) deserialisieren möchten, implementieren Sie DeepLinkSerializer<T> für den Elementtyp T und versehen Sie das Typargument des Attributs mit @Serializable(with = ...):

Begrenzte Sammlungen in einzelnen Parametern

Wenn Sie kommagetrennte oder benutzerdefinierte Werte (z. B. ?ids=1,2,3) in eine Sammlung parsen möchten, implementieren Sie DeepLinkSerializer für den gesamten Sammlungstyp und versehen Sie das Attribut mit @Serializable(with = ...):

Argumentvalidierung und Abgleichsergebnisse

UriDeepLinkMatcher unterscheidet zwischen Abweichungen (gibt null zurück, damit andere Matcher versucht werden können) und nicht unterstützten Konfigurationen (löst eine Ausnahme aus).

Abweichungen

Eine Abweichung tritt auf, wenn eine eingehende Anfrage-URI nicht den Muster- oder Typanforderungen entspricht:

  • Fehlende erforderliche Parameter: Nicht nullable-Schlüsselattribute ohne Standard werte, deren entsprechende URI-Parameter in der Anfrage-URI fehlen.
  • Fehler beim Parsen von Typen: Extrahierte Argumentwerte, die nicht in den erwarteten Attributtyp geparst werden können (z. B. "abc" für ein Int Attribut).

Wenn eine Abweichung auftritt, gibt UriDeepLinkMatcher.match null zurück, sodass nachfolgende Matcher ausgewertet werden können.

Betrachten Sie eine Schlüsselklasse und einen Matcher, die mit Standardwerten, verschachtelten Objekten und Enums konfiguriert sind:

In der folgenden Tabelle sind die Abgleichsergebnisse für verschiedene Anfrage-URIs dargestellt:

Anfrage-URI Ergebnis der Decodierung Abgleichsergebnis
https://www.example.com/map/paris?zoom=15&style=dark&layer=SATELLITE Erfolg (Alle Parameter angegeben) UriMatchResult(MapKey("paris", 15, LayerOptions("dark", MapLayer.SATELLITE)))
https://www.example.com/map/paris?style=dark Erfolg (zoom wird standardmäßig auf 12 und layer auf STANDARD gesetzt) UriMatchResult(MapKey("paris", 12, LayerOptions("dark", MapLayer.STANDARD)))
https://www.example.com/map/paris?zoom=&style=dark Erfolg (Leerer optionaler Abfrageparameter verwendet Standardwert 12) UriMatchResult(MapKey("paris", 12, LayerOptions("dark", MapLayer.STANDARD)))
https://www.example.com/map?style=dark Abweichung (Erforderlicher Parameter location fehlt) null
https://www.example.com/map/paris?zoom=close&style=dark Abweichung ("close" ist kein Int) null
https://www.example.com/map/paris?style=dark&layer=HYBRID Abweichung ("HYBRID" ist nicht im Enum enthalten) null

Nicht unterstützte Konfigurationen

Wenn Ihre Schlüsselklasse nicht unterstützte Datentypen enthält, löst UriDeepLinkMatcher während des Abgleichs eine Ausnahme aus, anstatt null zurückzugeben.

  • Maps und mehrdimensionale Sammlungen: UriDeepLinkMatcher unterstützt nur eindimensionale Sammlungen von primitiven Typen, Strings, Enums oder benutzerdefinierten Typen, die mit einem DeepLinkSerializer versehen sind. Map-Typen lösen eine IllegalArgumentException aus, während verschachtelte Sammlungen (z. B. List<List<String>>) eine SerializationException auslösen.
  • Nicht annotierte Sammlungen benutzerdefinierter Objekte: Sammlungen benutzerdefinierter Typen (z. B. List<Filter>) lösen eine SerializationException aus, es sei denn, der Elementtyp ist mit einem DeepLinkSerializer versehen.
  • Nicht umgewandelte verschachtelte Klassen: Verschachtelte @Serializable Klassen können ohne DeepLinkSerializer nicht einem einzelnen Platzhalter (z. B. ?user={user}) zugeordnet werden.

UriMatchResult-Vergleich

UriMatchResult -Instanzen werden anhand der folgenden Kriterien in der angegebenen Reihenfolge bewertet:

  1. MatchResult-Typ: UriMatchResult wird höher bewertet als andere MatchResult Typen.
  2. Genauer Pfad: Literale Pfadübereinstimmungen werden höher bewertet als Übereinstimmungen mit Platzhaltern oder Wildcards.
  3. Anzahl der Pfadargumente: Übereinstimmungen mit mehr Pfadargumenten werden höher bewertet.
  4. Vorhandensein von Argumenten: Übereinstimmungen, die Argumente erfassen, werden höher bewertet als solche, die keine Argumente erfassen.
  5. Gesamtzahl der Argumente: Die Gesamtzahl der Argumente (Pfad, Abfrage, Fragment) ist der letzte Entscheidungsfaktor.

UriDeepLinkMatcher anpassen

UriDeepLinkMatcher ist eine open-Klasse, die Sie unterteilen können, um das Verhalten beim URI-Abgleich und bei der Argumentextraktion anzupassen:

  • matchRequest: Einstiegspunkt für den Abgleich auf oberster Ebene für eine eingehende DeepLinkRequest. Überschreiben Sie diese Methode, um zusätzliche Anfragen zu prüfen oder benutzerdefinierte Vorbedingungen anzuwenden, bevor der URI-Abgleich erfolgt.
  • matchUri: Gleicht die DeepLinkUri mit dem konfigurierten Muster ab. Überschreiben Sie diese Methode, um eingehende URIs abzufangen und zu normalisieren (z. B. dynamische Subdomains oder Legacy-Pfadformate neu zu schreiben), bevor Sie super.matchUri aufrufen.
  • matchArguments: Deserialisiert die extrahierten Argumentzuordnungen für Pfad, Abfrage und Fragment mithilfe des angegebenen serializer in eine Navigationsschlüsselinstanz. Überschreiben Sie diese Methode, um dynamische Werte einzufügen oder Argumente vor der Schlüsselinstanziierung zu transformieren.

Im folgenden Beispiel wird gezeigt, wie Sie eine Unterklasse von UriDeepLinkMatcher erstellen, um Legacy-URL-Pfadpräfixe vor dem Abgleich zu normalisieren: