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

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

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

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

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

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

تطبیق طرح

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

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

شمارشی‌ها

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

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

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

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

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

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

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

برای رمزگشایی کردن شیء از رشته پارامتر نشانی وب تکی (مثل ?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 را برمی‌گرداند تا تطابق‌دهنده‌های دیگر امتحان شوند) و پیکربندی‌های پشتیبانی‌نشده (استثنایی ایجاد می‌کند) تمایز قائل می‌شود.

عدم تطابق‌ها

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

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

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

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

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

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" در شمارش نیست) 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 است که می‌توانید آن را زیرکلاس کنید تا رفتار استخراج آرگومان و مطابقت نشانی وب را سفارشی‌سازی کنید:

  • matchRequest: نقطه ورود تطبیق سطح بالا برای DeepLinkRequest ورودی. برای بازرسی کردن موارد اضافی درخواست یا اعمال پیش‌شرط‌های سفارشی قبل‌از مطابقت با نشانی وب، این مورد را ملغی کنید.
  • matchUri: DeepLinkUri را با الگوی پیکربندی‌شده مطابقت می‌دهد. برای رهگیری و عادی‌سازی کردن نشانی‌های وب ورودی (برای مثال، بازنویسی زیردامنه‌های پویا یا قالب‌های مسیر قدیمی) قبل‌از فراخوانی super.matchUri، این را ملغی کنید.
  • matchArguments: نقشه‌های آرگومان مسیر، پُرسمان، و تکه‌برداری استخراج‌شده را بااستفاده از serializer ارائه‌شده به نمونه کلید ناوبری واسریال‌سازی می‌کند. برای تزریق مقادیر پویا یا تبدیل آرگومان‌ها قبل‌از نمونه‌سازی کلید، این را ملغی کنید.

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