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

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

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

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

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

UriDeepLinkMatcher URIها را بر اساس پنج مؤلفه‌ی آنها تطبیق می‌دهد: طرحواره (scheme)، اعتبار (authority)، مسیر (path)، پرس‌وجو (query) و قطعه قطعه (fragment). بخش‌های زیر، سینتکس الگوی پشتیبانی‌شده، متغیرهای آرگومان و قوانین تطبیق برای هر مؤلفه را شرح می‌دهند.

تطبیق طرح

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

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

  • سریال‌سازی استاندارد : از kotlinx.serialization برای deserialize کردن به صورت زیر استفاده می‌کند:
    • مقادیر اولیه ( Boolean ، Int ، Long ، Float ، Double ، Char ، Byte ، Short ) و String
    • انوم‌ها
    • Set ، List یا Array از مقادیر اولیه، رشته‌ها یا enumها
    • کلاس‌های تو در تو @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 مجزا با همان نام نگاشت می‌شود:

برای deserialize کردن اشیاء سفارشی (مانند 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 = ...) حاشیه‌نویسی کنید:

اشیاء سفارشی در پارامترهای پرس و جوی مکرر

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

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

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

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

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

عدم تطابق‌ها

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

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

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

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

جدول زیر نتایج منطبق برای 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 یک استثنا ایجاد می‌کند.

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

مقایسه UriMatchResult

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

  1. نوع MatchResult : UriMatchResult رتبه بالاتری نسبت به سایر انواع MatchResult دارد.
  2. مسیر دقیق : تطابق‌های مسیر تحت‌اللفظی رتبه بالاتری نسبت به تطابق‌های placeholder یا wildcard دارند.
  3. تعداد آرگومان مسیر : تطابق‌هایی که آرگومان‌های مسیر بیشتری داشته باشند، رتبه بالاتری دارند.
  4. وجود آرگومان‌ها : تطابق‌هایی که آرگومان‌ها را در بر می‌گیرند، رتبه بالاتری نسبت به تطابق‌هایی که ندارند، کسب می‌کنند.
  5. تعداد کل آرگومان‌ها : تعداد کل آرگومان‌ها (مسیر، پرس‌وجو، قطعه کد) آخرین معیار برای تعیین گره است.

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

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

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

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