पैटर्न के हिसाब से क्रम में लगे यूआरआई का मिलान करने और आर्ग्युमेंट निकालने के लिए, UriDeepLinkMatcher का इस्तेमाल करें. यह मैच किए गए आर्ग्युमेंट को आपकी मुख्य क्लास में डीसीरियलाइज़ करने के लिए, kotlinx.serialization पर निर्भर करता है.
UriDeepLinkMatcher बनाने के लिए, DeepLinkUri का पैटर्न और उससे जुड़ी मुख्य क्लास के लिए
सीरियलाइज़र उपलब्ध कराएं:
@Serializable data class UserProfileKey(val id: String) : NavKey val userProfilePattern = DeepLinkUri("www.example.com/users/{id}") val userProfileMatcher = UriDeepLinkMatcher(userProfilePattern, serializer<UserProfileKey>()) val request = DeepLinkRequest(uri = "https://www.example.com/users/123") val matchResult = userProfileMatcher.match(request) val key = matchResult?.key // UserProfileKey(id = "123")
क्रम में न लगे यूआरआई या कस्टम स्कीम (जैसे, tel:) के लिए,
कस्टम डीप लिंक मैच करने वाले टूल बनाना लेख पढ़ें.
मैच करने के लिए काम करने वाले पैटर्न
UriDeepLinkMatcher , यूआरआई को उनके पांच कॉम्पोनेंट के आधार पर मैच करता है: स्कीम, अथॉरिटी, पाथ, क्वेरी, और फ़्रैगमेंट. इन सेक्शन में, हर कॉम्पोनेंट के लिए काम करने वाले पैटर्न सिंटैक्स, आर्ग्युमेंट प्लेसहोल्डर, और मैच करने के नियमों के बारे में बताया गया है.
स्कीम मैच करना
अगर यूआरआई पैटर्न में कोई स्कीम मौजूद नहीं है, तो http और https दोनों मैच किए जाते हैं.
किसी खास स्कीम को मैच करने के लिए, उसे पैटर्न में शामिल करें. हालांकि, पैटर्न में मौजूद
http स्कीम, http और https दोनों तरह के अनुरोध वाले यूआरआई से मैच करती है. वहीं, पैटर्न में मौजूद
https स्कीम सिर्फ़ https अनुरोधों से मैच करती है.
| पैटर्न यूआरआई | अनुरोध यूआरआई | मिलते-जुलते वीडियो |
|---|---|---|
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 |
✅ |
अथॉरिटी मैच करना
UriDeepLinkMatcher , यूआरआई अथॉरिटी (होस्ट और पोर्ट, अगर मौजूद हो) पर केस-इनसेंसिटिव सटीक मैच करता है. अथॉरिटी में प्लेसहोल्डर या वाइल्डकार्ड इस्तेमाल नहीं किए जा सकते. साथ ही, कोई आर्ग्युमेंट नहीं निकाला जाता:
| पैटर्न यूआरआई | अनुरोध यूआरआई | मिलते-जुलते वीडियो |
|---|---|---|
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 |
❌ |
पाथ मैच करना
पाथ के इन पैटर्न का इस्तेमाल किया जा सकता है:
| पैटर्न यूआरआई | अनुरोध यूआरआई | मिलते-जुलते वीडियो | निकाले गए आर्ग्युमेंट |
|---|---|---|---|
www.example.com/users |
https://www.example.com/users |
✅ | कोई नहीं |
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: "" (खाली स्ट्रिंग) |
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 |
✅ | कोई नहीं |
www.example.com/users |
https://www.example.com/users/ |
❌ (आखिर में स्लैश लगाने से एक और सेगमेंट बन जाता है) | लागू नहीं |
क्वेरी मैच करना
अनुरोध URI में क्वेरी पैरामीटर का क्रम, पैटर्न URI के क्रम से मैच होना ज़रूरी नहीं है. इसके अलावा, अनुरोध URI में मौजूद ऐसे पैरामीटर को अनदेखा किया जाता है जो पैटर्न URI में मौजूद नहीं होते.
क्वेरी पैरामीटर के इन पैटर्न का इस्तेमाल किया जा सकता है:
| पैटर्न यूआरआई | अनुरोध यूआरआई | निकाले गए आर्ग्युमेंट |
|---|---|---|
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: "" (खाली स्ट्रिंग) |
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" |
फ़्रैगमेंट मैच करना
फ़्रैगमेंट के इन पैटर्न टाइप का इस्तेमाल किया जा सकता है:
| पैटर्न यूआरआई | अनुरोध यूआरआई | निकाले गए आर्ग्युमेंट |
|---|---|---|
www.example.com/#section1 |
https://www.example.com/#section1 |
कोई नहीं |
www.example.com/#section_{id} |
https://www.example.com/#section_123 |
id: "123" |
www.example.com/#section_.* |
https://www.example.com/#section_123 |
कोई नहीं |
किस तरह के डेटा को ट्रांसफ़र किया जा सकता है
UriDeepLinkMatcher , यूआरआई आर्ग्युमेंट को प्रिमिटिव टाइप, एनम, कलेक्शन, और कस्टम ऑब्जेक्ट में डीसीरियलाइज़ कर सकता है. सीरियलाइज़ेशन को दो कैटगरी में बांटा गया है:
- स्टैंडर्ड सीरियलाइज़ेशन: इसमें
kotlinx.serializationका इस्तेमाल करके, इन्हें डीसीरियलाइज़ किया जाता है into:- प्रिमिटिव (
Boolean,Int,Long,Float,Double,Char,Byte,Short) औरString - एनम्स
- प्रिमिटिव, स्ट्रिंग या एनम का
Set,ListयाArray - नेस्ट की गई
@Serializableक्लास (जिनकी प्रॉपर्टी को अलग-अलग यूआरआई प्लेसहोल्डर में फ़्लैट किया जाता है)
- प्रिमिटिव (
DeepLinkSerializerके साथ कस्टम सीरियलाइज़ेशन: यह एकStringऔर कस्टम ऑब्जेक्ट, बाहरी टाइप (जैसे,java.time.LocalDate) या कस्टम-डेलिमिटेड कलेक्शन के बीच कन्वर्ज़न करता है.
स्टैंडर्ड सीरियलाइज़ेशन
UriDeepLinkMatcher , स्टैंडर्ड टाइप और फ़्लैट की गई संरचनाओं के लिए, बिना किसी कस्टम सीरियलाइज़र के लागू किए काम करता है.
प्रिमिटिव और स्ट्रिंग
UriDeepLinkMatcher , प्रिमिटिव टाइप (Boolean, Int, Long, Float, Double, Char, Byte, Short) और String को अपने-आप डिकोड करता है:
@Serializable data class UserProfileKey(val id: Int) : NavKey val matcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ) val request = DeepLinkRequest(uri = "https://www.example.com/users/123") val key = matcher.match(request)?.key // UserProfileKey(id = 123)
एनम्स
एनम की वैल्यू, एनम एलिमेंट के नामों के हिसाब से केस-सेंसिटिव तरीके से मैच की जाती हैं:
enum class SortOrder { RELEVANCE, DATE, POPULARITY } @Serializable data class ProductsKey(val sort: SortOrder) : NavKey val matcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/products?sort={sort}"), serializer<ProductsKey>() ) val request = DeepLinkRequest(uri = "https://www.example.com/products?sort=DATE") val key = matcher.match(request)?.key // ProductsKey(sort = SortOrder.DATE)
बार-बार इस्तेमाल होने वाले क्वेरी कलेक्शन
बार-बार इस्तेमाल होने वाली कुंजियों वाले क्वेरी पैरामीटर (जैसे, ?id=10&id=20) अपने-आप
List<T>, Set<T>, या Array<T> में डीसीरियलाइज़ हो जाते हैं. यहां T एक प्रिमिटिव
टाइप, String, या एनम होता है:
@Serializable data class FilteredItemsKey(val ids: List<Int>) : NavKey val matcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/items?id={ids}"), serializer<FilteredItemsKey>() ) val request = DeepLinkRequest(uri = "https://www.example.com/items?id=10&id=20") val key = matcher.match(request)?.key // FilteredItemsKey(ids = listOf(10, 20))
नेस्ट की गई @Serializable क्लास
जब किसी NavKey में ऐसी प्रॉपर्टी होती है जिसका टाइप, दूसरी @Serializable क्लास होता है, तो UriDeepLinkMatcher उसकी प्रॉपर्टी को फ़्लैट कर देता है. इससे नेस्ट की गई क्लास की हर प्रॉपर्टी, उसी नाम के किसी यूआरआई पैरामीटर से सीधे तौर पर मैप हो जाती है:
enum class SortOrder { RELEVANCE, DATE, POPULARITY } @Serializable data class SearchFilters( val category: String, val sortBy: SortOrder = SortOrder.RELEVANCE ) @Serializable data class SearchKey( val query: String, val page: Int = 1, // Flattened into {category} and {sortBy} val filters: SearchFilters ) : NavKey val matcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/search?q={query}&page={page}&category={category}&sortBy={sortBy}"), serializer<SearchKey>() ) val request = DeepLinkRequest(uri = "https://www.example.com/search?q=kotlin&category=books&sortBy=DATE") val key = matcher.match(request)?.key // SearchKey(query = "kotlin", page = 1, filters = SearchFilters(category = "books", sortBy = SortOrder.DATE))
DeepLinkSerializer के साथ कस्टम सीरियलाइज़ेशन
कस्टम ऑब्जेक्ट (जैसे, Filter(key = "brand", value =
"pixel")), बाहरी टाइप (जैसे, java.time.LocalDate) या कस्टम डेलिमिटेड
स्ट्रिंग (जैसे, कॉमा से अलग की गई वैल्यू) को डीसीरियलाइज़ करने के लिए, DeepLinkSerializer<T> को बढ़ाएं.
DeepLinkSerializer<T> एक ऐब्स्ट्रैक्ट KSerializer<T> है, जो String और T के बीच कन्वर्ज़न करता है:
abstract class DeepLinkSerializer<T : Any> : KSerializer<T> {
abstract val serialName: String
abstract fun deserialize(value: String): T
abstract fun serialize(value: T): String
}
उदाहरण के लिए, Filter और FilterSerializer की उन परिभाषाओं पर विचार करें जिनका इस्तेमाल, यहां दिए गए स्निपेट में किया गया है:
@Serializable data class Filter(val key: String, val value: String) object FilterSerializer : DeepLinkSerializer<Filter>() { override val serialName: String = "com.example.Filter" override fun deserialize(value: String): Filter { val parts = value.split(":", limit = 2) if (parts.size < 2) { throw SerializationException("Invalid filter: $value. Expected key:value.") } return Filter(key = parts[0], value = parts[1]) } override fun serialize(value: Filter): String = "${value.key}:${value.value}" }
सिंगल कस्टम ऑब्जेक्ट
किसी ऑब्जेक्ट को सिंगल यूआरआई पैरामीटर स्ट्रिंग (जैसे, ?filter=brand:google) से डिकोड करने के लिए, प्रॉपर्टी को @Serializable(with = ...) से एनोटेट करें:
@Serializable data class CatalogKey( @Serializable(with = FilterSerializer::class) val filter: Filter ) : NavKey val matcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/catalog?filter={filter}"), serializer<CatalogKey>() ) val request = DeepLinkRequest(uri = "https://www.example.com/catalog?filter=brand:google") val key = matcher.match(request)?.key // CatalogKey(filter = Filter("brand", "google"))
बार-बार इस्तेमाल होने वाले क्वेरी पैरामीटर में कस्टम ऑब्जेक्ट
बार-बार इस्तेमाल होने वाले क्वेरी पैरामीटर को कस्टम ऑब्जेक्ट
(List<T>, Set<T>, या Array<T>) के कलेक्शन में डीसीरियलाइज़ करने के लिए, DeepLinkSerializer<T> को
एलिमेंट टाइप T के लिए लागू करें. साथ ही, प्रॉपर्टी के टाइप आर्ग्युमेंट को
@Serializable(with = ...) से एनोटेट करें:
@Serializable data class SearchResultsKey( val query: String, val filters: List<@Serializable(with = FilterSerializer::class) Filter> = emptyList() ) : NavKey val searchResultsPattern = DeepLinkUri("www.example.com/search?q={query}&filter={filters}") val searchResultsMatcher = UriDeepLinkMatcher(searchResultsPattern, serializer<SearchResultsKey>()) val request = DeepLinkRequest(uri = "https://www.example.com/search?q=phone&filter=brand:google&filter=color:hazel") val matchResult = searchResultsMatcher.match(request) val key = matchResult?.key // SearchResultsKey(query = "phone", filters = listOf(Filter("brand", "google"), Filter("color", "hazel")))
सिंगल पैरामीटर में डेलिमिटेड कलेक्शन
कॉमा से अलग की गई या कस्टम-डेलिमिटेड वैल्यू (जैसे, ?ids=1,2,3) को कलेक्शन में पार्स करने के लिए, पूरे कलेक्शन टाइप के लिए DeepLinkSerializer लागू करें. साथ ही, प्रॉपर्टी को @Serializable(with = ...) से एनोटेट करें:
object IntListCsvSerializer : DeepLinkSerializer<List<Int>>() { override val serialName: String = "com.example.IntListCsv" override fun deserialize(value: String): List<Int> { if (value.isEmpty()) return emptyList() return value.split(",").map { it.trim().toInt() } } override fun serialize(value: List<Int>): String = value.joinToString(",") } @Serializable data class ItemListKey( @Serializable(with = IntListCsvSerializer::class) val ids: List<Int> ) : NavKey val itemListPattern = DeepLinkUri("www.example.com/items/{ids}") val itemListMatcher = UriDeepLinkMatcher(itemListPattern, serializer<ItemListKey>()) val request = DeepLinkRequest(uri = "https://www.example.com/items/10,20,30") val key = itemListMatcher.match(request)?.key // ItemListKey(ids = listOf(10, 20, 30))
आर्ग्युमेंट की पुष्टि करना और मैच करने के नतीजे
UriDeepLinkMatcher , मैच न होने (यह null दिखाता है, ताकि दूसरे मैच करने वाले टूल का इस्तेमाल किया जा सके) और काम न करने वाले कॉन्फ़िगरेशन (यह एक अपवाद दिखाता है) के बीच अंतर करता है.
मैच न होना
मैच न होने की स्थिति तब होती है, जब आने वाले अनुरोध URI, पैटर्न या टाइप की ज़रूरी शर्तों को पूरा नहीं करता:
- ज़रूरी पैरामीटर मौजूद नहीं हैं: डिफ़ॉल्ट वैल्यू के बिना, नॉन-नलेबल की प्रॉपर्टी. साथ ही, अनुरोध URI में उनसे जुड़े URI पैरामीटर मौजूद नहीं हैं.
- टाइप पार्स करने में गड़बड़ियां: निकाले गए आर्ग्युमेंट की वैल्यू को, अनुमानित प्रॉपर्टी टाइप में पार्स नहीं किया जा सकता. उदाहरण के लिए,
"abc"प्रॉपर्टी के लिएInt.
मैच न होने की स्थिति में, UriDeepLinkMatcher.match, null दिखाता है. इससे बाद के मैच करने वाले टूल का आकलन किया जा सकता है.
डिफ़ॉल्ट वैल्यू, नेस्ट किए गए ऑब्जेक्ट, और एनम के साथ कॉन्फ़िगर की गई की क्लास और मैच करने वाले टूल पर विचार करें:
enum class MapLayer { STANDARD, SATELLITE, TERRAIN } @Serializable data class LayerOptions( val style: String, val layer: MapLayer = MapLayer.STANDARD ) @Serializable data class MapKey( val location: String, val zoom: Int = 12, val options: LayerOptions ) : NavKey val matcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/map/{location}?zoom={zoom}&style={style}&layer={layer}"), serializer<MapKey>() )
यहां दी गई टेबल में, अलग-अलग अनुरोध वाले यूआरआई के लिए मैच करने के नतीजों को दिखाया गया है:
| अनुरोध यूआरआई | डिकोड करने का नतीजा | मैच का नतीजा |
|---|---|---|
https://www.example.com/map/paris?zoom=15&style=dark&layer=SATELLITE |
पूरा हुआ (सभी पैरामीटर दिए गए हैं) | UriMatchResult(MapKey("paris", 15, LayerOptions("dark", MapLayer.SATELLITE))) |
https://www.example.com/map/paris?style=dark |
पूरा हुआ (zoom की डिफ़ॉल्ट वैल्यू 12 और layer की डिफ़ॉल्ट वैल्यू STANDARD है) |
UriMatchResult(MapKey("paris", 12, LayerOptions("dark", MapLayer.STANDARD))) |
https://www.example.com/map/paris?zoom=&style=dark |
पूरा हुआ (खाली वैकल्पिक क्वेरी पैरामीटर, डिफ़ॉल्ट वैल्यू 12 का इस्तेमाल करता है) |
UriMatchResult(MapKey("paris", 12, LayerOptions("dark", MapLayer.STANDARD))) |
https://www.example.com/map?style=dark |
मैच नहीं हुआ (ज़रूरी location पैरामीटर मौजूद नहीं है) |
null |
https://www.example.com/map/paris?zoom=close&style=dark |
मैच नहीं हुआ ("close" `Int` नहीं हैInt) |
null |
https://www.example.com/map/paris?style=dark&layer=HYBRID |
मैच नहीं हुआ ("HYBRID" एनम में नहीं है) |
null |
काम न करने वाले कॉन्फ़िगरेशन
अगर आपकी की क्लास में काम न करने वाले डेटा टाइप मौजूद हैं, तो UriDeepLinkMatcher, null दिखाने के बजाय, मैच करने के दौरान एक अपवाद दिखाता है.
- मैप और मल्टी-डाइमेंशनल कलेक्शन:
UriDeepLinkMatcherसिर्फ़ प्रिमिटिव, स्ट्रिंग, एनम या कस्टम टाइप के सिंगल-डाइमेंशनल कलेक्शन के साथ काम करता है, जिन्हेंDeepLinkSerializerसे एनोटेट किया गया है.Mapटाइप, दिखाता है. वहीं, नेस्ट किए गए कलेक्शन (जैसे,List<List<String>>),SerializationExceptionदिखाते हैं.IllegalArgumentException - बिना एनोटेशन वाले कस्टम ऑब्जेक्ट कलेक्शन: कस्टम टाइप के कलेक्शन (जैसे,
List<Filter>)SerializationExceptionदिखाते हैं. हालांकि, अगर एलिमेंट टाइप कोDeepLinkSerializerसे एनोटेट किया गया है, तो ऐसा नहीं होता. - बिना फ़्लैट की गई नेस्ट की गई क्लास: नेस्ट की गई
@Serializableक्लास को, सिंगल प्लेसहोल्डर (जैसे,?user={user}) से,DeepLinkSerializerके बिना मैप नहीं किया जा सकता.
// Throws IllegalArgumentException: Map decoding is not supported. @Serializable data class InvalidKey(val tags: Map<String, String>) : NavKey // Throws SerializationException: Only collections of primitives are supported. @Serializable data class InvalidKey(val filters: List<Filter>) : NavKey
UriMatchResult की तुलना करना
UriMatchResult इंस्टेंस को, क्रम से इन शर्तों के आधार पर रैंक किया जाता है:
- MatchResult टाइप:
UriMatchResultको,MatchResultकी तुलना में ज़्यादा रैंक मिलती है. - सटीक पाथ: प्लेसहोल्डर या वाइल्डकार्ड मैच की तुलना में, लिटरल पाथ मैच को ज़्यादा रैंक मिलती है.
- पाथ आर्ग्युमेंट की संख्या: ज़्यादा पाथ आर्ग्युमेंट वाले मैच को ज़्यादा रैंक मिलती है.
- आर्ग्युमेंट की मौजूदगी: आर्ग्युमेंट कैप्चर करने वाले मैच को, आर्ग्युमेंट कैप्चर न करने वाले मैच की तुलना में ज़्यादा रैंक मिलती है.
- आर्ग्युमेंट की कुल संख्या: पाथ, क्वेरी, फ़्रैगमेंट आर्ग्युमेंट की कुल संख्या, फ़ाइनल टाई-ब्रेकर होती है.
UriDeepLinkMatcher को पसंद के मुताबिक बनाना
UriDeepLinkMatcher , एक open क्लास है. इसे सबक्लास करके, यूआरआई मैच करने और आर्ग्युमेंट निकालने के तरीके को पसंद के मुताबिक बनाया जा सकता है:
matchRequest: आने वालेDeepLinkRequestके लिए, टॉप-लेवल मैचिंग एंट्री पॉइंट. अनुरोध के एक्सट्रा की जांच करने या यूआरआई मैच करने से पहले, कस्टम ज़रूरी शर्तें लागू करने के लिए, इसे बदलें.matchUri: कॉन्फ़िगर किए गए पैटर्न के हिसाब से,DeepLinkUriको मैच करता है.super.matchUriको कॉल करने से पहले, आने वाले यूआरआई को इंटरसेप्ट और सामान्य करने के लिए, इसे बदलें. उदाहरण के लिए, डाइनैमिक सबडोमेन या लेगसी पाथ फ़ॉर्मैट को फिर से लिखना.matchArguments: दिए गएserializerका इस्तेमाल करके, निकाले गए पाथ, क्वेरी, और फ़्रैगमेंट आर्ग्युमेंट मैप को नेविगेशन की इंस्टेंस में डीसीरियलाइज़ करता है. की इंस्टैंशिएशन से पहले, डाइनैमिक वैल्यू इंजेक्ट करने या आर्ग्युमेंट बदलने के लिए, इसे बदलें.
यहां दिए गए उदाहरण में, मैच करने से पहले, लेगसी यूआरएल पाथ प्रीफ़िक्स को सामान्य करने के लिए, UriDeepLinkMatcher को सबक्लास करने का तरीका बताया गया है:
class LegacyPrefixUriDeepLinkMatcher<T : Any>( uriPattern: DeepLinkUri, serializer: KSerializer<T> ) : UriDeepLinkMatcher<T>(uriPattern, serializer) { override fun matchUri(uri: DeepLinkUri): UriMatchResult<T>? { val path = uri.path val normalizedUri = if (path != null && path.startsWith("/legacy/")) { DeepLinkUri(uri.toString().replaceFirst("/legacy", "")) } else { uri } return super.matchUri(normalizedUri) } }