From eb64d76907a1b7e4305cc2ebfe78365c309da145 Mon Sep 17 00:00:00 2001 From: Gordan Ovcaric Date: Tue, 24 Mar 2026 12:08:52 +0100 Subject: [PATCH 1/2] CUST-5203: add "maybe" to Event Status, and gracefully handle unknown status --- src/main/kotlin/com/nylas/models/Event.kt | 2 +- .../kotlin/com/nylas/models/EventStatus.kt | 3 ++ .../com/nylas/util/EventStatusJsonAdapter.kt | 23 +++++++++ src/main/kotlin/com/nylas/util/JsonHelper.kt | 1 + .../kotlin/com/nylas/resources/EventsTests.kt | 50 +++++++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt diff --git a/src/main/kotlin/com/nylas/models/Event.kt b/src/main/kotlin/com/nylas/models/Event.kt index bd476a54..0931cb3f 100644 --- a/src/main/kotlin/com/nylas/models/Event.kt +++ b/src/main/kotlin/com/nylas/models/Event.kt @@ -110,7 +110,7 @@ data class Event( @Json(name = "reminders") val reminders: Reminders? = null, /** - * Status of the event. + * Status of the event. Possible values: "confirmed", "tentative", "cancelled", "maybe". */ @Json(name = "status") val status: EventStatus? = null, diff --git a/src/main/kotlin/com/nylas/models/EventStatus.kt b/src/main/kotlin/com/nylas/models/EventStatus.kt index 8c86995e..08aec3b5 100644 --- a/src/main/kotlin/com/nylas/models/EventStatus.kt +++ b/src/main/kotlin/com/nylas/models/EventStatus.kt @@ -9,6 +9,9 @@ enum class EventStatus { @Json(name = "confirmed") CONFIRMED, + @Json(name = "maybe") + MAYBE, + @Json(name = "tentative") TENTATIVE, diff --git a/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt b/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt new file mode 100644 index 00000000..b502b59a --- /dev/null +++ b/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt @@ -0,0 +1,23 @@ +package com.nylas.util + +import com.nylas.models.EventStatus +import com.squareup.moshi.FromJson +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.ToJson +import com.squareup.moshi.adapters.EnumJsonAdapter + +/** + * Handles EventStatus values without failing deserialization when the API returns a new status. + */ +class EventStatusJsonAdapter { + private val delegate = EnumJsonAdapter.create(EventStatus::class.java).withUnknownFallback(null) + + @FromJson + fun fromJson(reader: JsonReader): EventStatus? = delegate.fromJson(reader) + + @ToJson + fun toJson(writer: JsonWriter, value: EventStatus?) { + delegate.toJson(writer, value) + } +} diff --git a/src/main/kotlin/com/nylas/util/JsonHelper.kt b/src/main/kotlin/com/nylas/util/JsonHelper.kt index baa79ca2..c2b80a4e 100644 --- a/src/main/kotlin/com/nylas/util/JsonHelper.kt +++ b/src/main/kotlin/com/nylas/util/JsonHelper.kt @@ -36,6 +36,7 @@ class JsonHelper { .add(IMessageAdapter()) .add(UpdateConnectorAdapter()) .add(CredentialDataAdapter()) + .add(EventStatusJsonAdapter()) .add(CreateAttachmentRequestAdapter()) .add(MicrosoftAdminConsentCredentialDataAdapter()) .add(GoogleServiceAccountCredentialDataAdapter()) diff --git a/src/test/kotlin/com/nylas/resources/EventsTests.kt b/src/test/kotlin/com/nylas/resources/EventsTests.kt index df38cd9d..4fae4553 100644 --- a/src/test/kotlin/com/nylas/resources/EventsTests.kt +++ b/src/test/kotlin/com/nylas/resources/EventsTests.kt @@ -223,6 +223,56 @@ class EventsTests { assertEquals("2024-06-18", whenDate.date) } + @Test + fun `Event deserializes maybe status properly`() { + val adapter = JsonHelper.moshi().adapter(Event::class.java) + val jsonBuffer = + Buffer().writeUtf8( + """ + { + "id": "5d3qmne77v32r8l4phyuksl2x", + "grant_id": "41009df5-bf11-4c97-aa18-b285b5f2e386", + "calendar_id": "7d93zl2palhxqdy6e5qinsakt", + "object": "event", + "status": "maybe", + "when": { + "date": "2024-06-18", + "object": "date" + } + } + """.trimIndent(), + ) + + val event = adapter.fromJson(jsonBuffer)!! + + assertEquals(EventStatus.MAYBE, event.status) + } + + @Test + fun `Event deserializes unknown status as null`() { + val adapter = JsonHelper.moshi().adapter(Event::class.java) + val jsonBuffer = + Buffer().writeUtf8( + """ + { + "id": "5d3qmne77v32r8l4phyuksl2x", + "grant_id": "41009df5-bf11-4c97-aa18-b285b5f2e386", + "calendar_id": "7d93zl2palhxqdy6e5qinsakt", + "object": "event", + "status": "unexpected_status", + "when": { + "date": "2024-06-18", + "object": "date" + } + } + """.trimIndent(), + ) + + val event = adapter.fromJson(jsonBuffer)!! + + assertEquals(null, event.status) + } + @Test fun `CreateEventAutoConferencingProvider serializes properly`() { val adapter = JsonHelper.moshi().adapter(CreateEventAutoConferencingProvider::class.java) From a1c4a296a2af5e470edfe2b6bea633256563ab51 Mon Sep 17 00:00:00 2001 From: Gordan Ovcaric Date: Tue, 24 Mar 2026 17:02:10 +0100 Subject: [PATCH 2/2] Set TENTATIVE as deprecated, use MAYBE instead --- .../kotlin/com/nylas/models/EventStatus.kt | 4 +++ .../com/nylas/util/EventStatusJsonAdapter.kt | 26 ++++++++++---- .../kotlin/com/nylas/resources/EventsTests.kt | 34 +++++++++++++++++++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/nylas/models/EventStatus.kt b/src/main/kotlin/com/nylas/models/EventStatus.kt index 08aec3b5..0e69e1c4 100644 --- a/src/main/kotlin/com/nylas/models/EventStatus.kt +++ b/src/main/kotlin/com/nylas/models/EventStatus.kt @@ -12,6 +12,10 @@ enum class EventStatus { @Json(name = "maybe") MAYBE, + @Deprecated( + message = "Use MAYBE instead. TENTATIVE is a legacy alias and will be removed in a future release.", + replaceWith = ReplaceWith("MAYBE"), + ) @Json(name = "tentative") TENTATIVE, diff --git a/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt b/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt index b502b59a..25ad2bf7 100644 --- a/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt +++ b/src/main/kotlin/com/nylas/util/EventStatusJsonAdapter.kt @@ -5,19 +5,33 @@ import com.squareup.moshi.FromJson import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.ToJson -import com.squareup.moshi.adapters.EnumJsonAdapter /** - * Handles EventStatus values without failing deserialization when the API returns a new status. + * Normalizes legacy event status values and avoids failing deserialization on new values. */ class EventStatusJsonAdapter { - private val delegate = EnumJsonAdapter.create(EventStatus::class.java).withUnknownFallback(null) - @FromJson - fun fromJson(reader: JsonReader): EventStatus? = delegate.fromJson(reader) + fun fromJson(reader: JsonReader): EventStatus? { + if (reader.peek() == JsonReader.Token.NULL) { + return reader.nextNull() + } + + return when (reader.nextString()) { + "confirmed" -> EventStatus.CONFIRMED + "maybe", "tentative" -> EventStatus.MAYBE + "cancelled" -> EventStatus.CANCELLED + else -> null + } + } @ToJson + @Suppress("DEPRECATION") fun toJson(writer: JsonWriter, value: EventStatus?) { - delegate.toJson(writer, value) + when (value) { + null -> writer.nullValue() + EventStatus.CONFIRMED -> writer.value("confirmed") + EventStatus.MAYBE, EventStatus.TENTATIVE -> writer.value("maybe") + EventStatus.CANCELLED -> writer.value("cancelled") + } } } diff --git a/src/test/kotlin/com/nylas/resources/EventsTests.kt b/src/test/kotlin/com/nylas/resources/EventsTests.kt index 4fae4553..8778d122 100644 --- a/src/test/kotlin/com/nylas/resources/EventsTests.kt +++ b/src/test/kotlin/com/nylas/resources/EventsTests.kt @@ -248,6 +248,31 @@ class EventsTests { assertEquals(EventStatus.MAYBE, event.status) } + @Test + fun `Event deserializes tentative status as maybe`() { + val adapter = JsonHelper.moshi().adapter(Event::class.java) + val jsonBuffer = + Buffer().writeUtf8( + """ + { + "id": "5d3qmne77v32r8l4phyuksl2x", + "grant_id": "41009df5-bf11-4c97-aa18-b285b5f2e386", + "calendar_id": "7d93zl2palhxqdy6e5qinsakt", + "object": "event", + "status": "tentative", + "when": { + "date": "2024-06-18", + "object": "date" + } + } + """.trimIndent(), + ) + + val event = adapter.fromJson(jsonBuffer)!! + + assertEquals(EventStatus.MAYBE, event.status) + } + @Test fun `Event deserializes unknown status as null`() { val adapter = JsonHelper.moshi().adapter(Event::class.java) @@ -273,6 +298,15 @@ class EventsTests { assertEquals(null, event.status) } + @Suppress("DEPRECATION") + @Test + fun `Event status serializes tentative as maybe`() { + val adapter = JsonHelper.moshi().adapter(EventStatus::class.java) + + assertEquals("\"maybe\"", adapter.toJson(EventStatus.MAYBE)) + assertEquals("\"maybe\"", adapter.toJson(EventStatus.TENTATIVE)) + } + @Test fun `CreateEventAutoConferencingProvider serializes properly`() { val adapter = JsonHelper.moshi().adapter(CreateEventAutoConferencingProvider::class.java)