مطابقت پیوندهای عمیق نشانی وب

برای مطابقت دادن URIهای سلسله‌مراتبی با الگوها و استخراج آرگومان‌ها، از UriDeepLinkMatcher استفاده کنید. این روش برای تبدیل آرگومان‌های مطابقت‌داده‌شده به کلاس‌های کلیدی شما، به kotlinx.serialization متکی است.

برای ایجاد UriDeepLinkMatcher، الگوی DeepLinkUri و سریال‌ساز را برای کلید مربوطه ارائه دهید:

برای URIهای غیرسلسله‌مراتبی یا طرح‌های سفارشی (مانند tel:)، به ایجاد تطبیق‌دهنده‌های پیوند عمیق سفارشی مراجعه کنید.

الگوهای تطبیق پشتیبانی‌شده

UriDeepLinkMatcher نشانی‌های وب را براساس پنج مؤلفه آن‌ها مطابقت می‌دهد: طرح، مرجع، مسیر، پُرسمان، و قطعه. بخش‌های زیر نحو الگوی پشتیبانی‌شده، جای‌بان‌های شناسه، و قوانین مطابقت را برای هر مؤلفه شرح می‌دهند.

مطابقت طرح

اگر طرح‌واره‌ای در الگوی URI وجود نداشته باشد، هم http و هم https مطابقت داده می‌شوند. برای مطابقت با طرحی خاص، آن را در الگو بگنجانید. به‌عنوان استثنا، طرح‌واره http در الگو با هر دو شناسه منبع یکسان درخواست http و https مطابقت دارد، درحالی‌که https در الگو فقط با درخواست‌های https مطابقت دارد.

URI الگو URI درخواست مطابق
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 تطابق دقیق غیرحساس به حروف بزرگ و کوچک را در مرجع URI (میزبان و درگاه اختیاری) انجام می‌دهد. از جای‌بان‌ها یا نویسه‌های عام در مرجع پشتیبانی نمی‌شود، و هیچ متغیر مستقلی استخراج نمی‌شود:

URI الگو URI درخواست مطابق
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 ❌

تطبیق مسیر

الگوهای مسیر زیر پشتیبانی می‌شوند:

URI الگو URI درخواست مطابق متغیرهای مستقل استخراج‌شده
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 الگو وجود ندارند نادیده گرفته می‌شوند.

الگوهای پارامتر پُرسمان زیر پشتیبانی می‌شوند:

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"

تطبیق قطعه

انواع الگوهای قطعه زیر پشتیبانی می‌شوند:

URI الگو URI درخواست متغیرهای مستقل استخراج‌شده
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 از غیرسریالی کردن آرگومان‌های URI به انواع اولیه، enum، مجموعه‌ها، و اشیای سفارشی پشتیبانی می‌کند. سریال‌سازی به دو دسته تقسیم می‌شود:

  • سریال‌سازی استاندارد: از kotlinx.serialization برای سریال‌زدایی به این موارد استفاده می‌کند:
    • ‫Primitives (Boolean،‏ Int،‏ Long،‏ Float،‏ Double،‏ Char،‏ Byte،‏ Short) و String
    • شمارشی‌ها
    • ‫Set،‏ List، یا Array از انواع داده‌های اولیه، رشته‌ها، یا شمارشی‌ها
    • کلاس‌های @Serializable تودرتو (که ویژگی‌های آن‌ها در جای‌بان‌های URI جداگانه مسطح شده است)
  • سریال‌سازی سفارشی با DeepLinkSerializer: بین یک String و اشیای سفارشی، انواع خارجی (مانند java.time.LocalDate)، یا مجموعه‌های با حدود سفارشی تبدیل می‌کند.

سریال‌سازی استاندارد

UriDeepLinkMatcher برای انواع استاندارد و ساختارهای مسطح بدون نیاز به پیاده‌سازی‌های سریال‌ساز سفارشی به‌طور پیش‌فرض کار می‌کند.

رشته‌ها و انواع داده‌های اولیه

‫UriDeepLinkMatcher به‌طور خودکار انواع اولیه (Boolean، Int، Long، Float، Double، Char، Byte، Short) و String را رمزگشایی می‌کند:

شمارشی‌ها

مقادیر Enum به‌صورت حروف‌حساس با نام‌های عنصر enum مطابقت داده می‌شوند:

مجموعه‌های پُرسمان تکراری

پارامترهای پُرسمان با کلیدهای تکراری (مانند ?id=10&id=20) به‌طور خودکار به List<T>، Set<T>، یا Array<T> که T نوعی اولیه، String، یا enum است، وازنجیره‌ای می‌شوند:

کلاس‌های @Serializable تودرتو

وقتی NavKey حاوی ویژگی‌ای باشد که نوع آن کلاس @Serializable دیگری است، UriDeepLinkMatcher ویژگی‌های آن را مسطح می‌کند تا هر ویژگی کلاس تودرتو مستقیماً به پارامتر URI جداگانه‌ای با همان نام نگاشت شود:

برای غیرسریالی کردن اشیای سفارشی (مثل 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 را که در قطعه‌های زیر استفاده شده‌اند درنظر بگیرید:

اشیای سفارشی تکی

برای رمزگشایی شیء از رشته پارامتر URI تکی (مانند ?filter=brand:google)، ویژگی را با @Serializable(with = ...) حاشیه‌نویسی کنید:

اشیاء سفارشی در پارامترهای پُرسمان تکراری

برای وازنجیرش پارامترهای پُرسمان تکراری در مجموعه‌ای از اشیای سفارشی (List<T>، Set<T>، یا Array<T>)، DeepLinkSerializer<T> را برای نوع عنصر T پیاده‌سازی کنید و شناسه نوع ویژگی را با @Serializable(with = ...) حاشیه‌نویسی کنید:

مجموعه‌های محدودشده در پارامترهای تکی

برای تجزیه کردن مقادیر جداشده با کاما یا جداشده با جداکننده سفارشی (مثل ?ids=1,2,3) در یک مجموعه، DeepLinkSerializer را برای کل نوع مجموعه پیاده‌سازی کنید و خصوصیت را با @Serializable(with = ...) حاشیه‌نویسی کنید:

اعتبارسنجی استدلال و نتایج تطبیق

UriDeepLinkMatcher بین عدم تطابق (null را برمی‌گرداند تا سایر تطبیق‌دهنده‌ها بتوانند امتحان شوند) و پیکربندی‌های پشتیبانی‌نشده (استثنا ایجاد می‌کند) تمایز قائل می‌شود.

ناسازگاری‌ها

عدم تطابق زمانی رخ می‌دهد که شناسه منبع یکنواخت درخواست ورودی، الزامات الگو یا نوع را برآورده نکند:

  • پارامترهای الزامی وجود ندارد: ویژگی‌های کلیدی غیرقابل‌تهی بدون مقادیر پیش‌فرض که پارامترهای URI مربوطه آن‌ها در URI درخواست وجود ندارد.
  • خطاهای تجزیه نوع: مقادیر متغیر مستقل استخراج‌شده که نمی‌توانند به نوع ویژگی موردانتظار تجزیه شوند (برای مثال، "abc" برای ویژگی Int).

وقتی عدم تطابق رخ می‌دهد، UriDeepLinkMatcher.match مقدار null را برمی‌گرداند، که اجازه می‌دهد تطبیق‌دهنده‌های بعدی ارزیابی شوند.

کلاس کلید و تطبیق‌دهنده‌ای را درنظر بگیرید که با مقادیر پیش‌فرض، اشیای تودرتو، و شمارش‌ها پیکربندی شده است:

جدول زیر نتایج مطابقت را برای شناسه‌های منبع یکسان درخواست‌های مختلف نشان می‌دهد:

URI درخواست نتیجه رمزگشایی نتیجه مسابقه
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 نیست) null
https://www.example.com/map/paris?style=dark&layer=HYBRID ناسازگاری ("HYBRID" در enum نیست) null

پیکربندی‌های پشتیبانی‌نشده

اگر کلاس کلید شما حاوی انواع داده‌های پشتیبانی‌نشده باشد، UriDeepLinkMatcher درطول تطبیق به‌جای برگرداندن null، استثنایی را ایجاد می‌کند.

  • مجموعه‌های چندبعدی و Maps: UriDeepLinkMatcher فقط از مجموعه‌های تک‌بعدی انواع اصلی، رشته‌ها، شمارشی‌ها، یا انواع سفارشی حاشیه‌نویسی‌شده با DeepLinkSerializer پشتیبانی می‌کند. انواع Map IllegalArgumentException را برمی‌گردانند، درحالی‌که مجموعه‌های تودرتو (مانند List<List<String>>) SerializationException را برمی‌گردانند.
  • مجموعه‌های شیء سفارشی حاشیه‌نویسی‌نشده: مجموعه‌های انواع سفارشی (مانند List<Filter>) SerializationException را برمی‌گردانند، مگراینکه نوع عنصر با DeepLinkSerializer حاشیه‌نویسی شده باشد.
  • کلاس‌های تودرتوی مسطح‌نشده: کلاس‌های تودرتوی @Serializable را نمی‌توان بدون DeepLinkSerializer به یک جای‌بان تکی (مانند ?user={user}) نگاشت کرد.

مقایسه UriMatchResult

نمونه‌های UriMatchResult بااستفاده از معیارهای زیر به‌ترتیب رتبه‌بندی می‌شوند:

  1. نوع MatchResult: UriMatchResult رتبه بالاتری نسبت به سایر انواع MatchResult دارد.
  2. مسیر دقیق: مطابقت‌های مسیر دقیق رتبه بالاتری نسبت به مطابقت‌های جای‌بان یا نویسه عام دارند.
  3. تعداد متغیر مستقل مسیر: مطابقت‌هایی که متغیرهای مستقل مسیر بیشتری دارند رتبه بالاتری می‌گیرند.
  4. وجود متغیرهای مستقل: مطابقت‌هایی که متغیرهای مستقل را ضبط می‌کنند رتبه بالاتری نسبت به مطابقت‌هایی دارند که این کار را نمی‌کنند.
  5. تعداد کل متغیرهای مستقل: تعداد کل متغیرهای مستقل (مسیر، پُرسمان، قطعه) تعیین‌کننده نهایی است.

سفارشی‌سازی UriDeepLinkMatcher

UriDeepLinkMatcher کلاسی open است که می‌توانید آن را زیرکلاس کنید تا رفتار استخراج متغیر مستقل و مطابقت URI را سفارشی‌سازی کنید:

  • matchRequest: نقطه ورودی تطبیق سطح بالا برای DeepLinkRequest ورودی. این را لغو کنید تا موارد اضافی درخواست را بازرسی کنید یا پیش‌شرط‌های سفارشی را قبل‌از تطبیق URI اعمال کنید.
  • ‫matchUri: DeepLinkUri را با الگوی پیکربندی‌شده مطابقت می‌دهد. این را لغو کنید تا URIهای ورودی را قبل‌از فراخوانی super.matchUri رهگیری و عادی‌سازی کنید (برای مثال، بازنویسی زیردامنه‌های پویا یا قالب‌های مسیر قدیمی).
  • matchArguments: Deserializes the extracted path, query, and fragment argument maps into a navigation key instance using the provided serializer. این را لغو کنید تا مقادیر پویا را تزریق کنید یا آرگومان‌ها را قبل‌از نمونه‌سازی کلید تبدیل کنید.

مثال زیر نشان می‌دهد که چطور می‌توان زیرکلاس UriDeepLinkMatcher را برای نرمال‌سازی پیشوندهای مسیر نشانی وب قدیمی قبل‌از مطابقت دادن ایجاد کرد: