# Unconfined Enums Adapter for Moshi

DevFeed: [Unconfined Enums Adapter for Moshi](<https://devfeed.tech/articles/unconfined-enums-adapter-for-moshi-25914.md>)

Original publisher: [Read original article](<https://medium.com/@xxfast/unconfined-enums-adapter-for-moshi-5d84542c8bf0?source=rss-43bae76e8f81------2>)

Author: Isuru Rajapakse

Published: 2022-05-11T12:08:49Z

Content type: tutorial

Language: en

Sources: [Stories by Isuru Rajapakse on Medium](<https://devfeed.tech/sources/stories-by-isuru-rajapakse-on-medium.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [LineageOS](<https://devfeed.tech/topics/lineageos.md>), [API](<https://devfeed.tech/topics/api.md>), [enum](<https://devfeed.tech/topics/enum.md>), [interfaces](<https://devfeed.tech/topics/interfaces.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [api](<https://devfeed.tech/tags/api.md>), [data-class](<https://devfeed.tech/tags/data-class.md>), [enum](<https://devfeed.tech/tags/enum.md>), [enum-class](<https://devfeed.tech/tags/enum-class.md>), [how-to](<https://devfeed.tech/tags/how-to.md>), [interfaces](<https://devfeed.tech/tags/interfaces.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [moshi](<https://devfeed.tech/tags/moshi.md>), [retrofit](<https://devfeed.tech/tags/retrofit.md>)

## AI overview

This tutorial presents a Kotlin pattern for handling previously unknown enum-like values from REST APIs with Moshi. It explains Moshi enum adapters, the unknown-value fallback, and an interface-based approach that preserves the server's raw value instead of mapping it only to a generic unknown value.

## Source excerpt

If you wonder what an Unconfined Enum is, wonder no more because it is a thing I just made up. Enums by definition are confined, or finite. Therefore "unconfined enum" is really an oxymoron. Nevertheless, say you have this Fruit enum and want to map each value to an Android string resource. Kotlin's enum properties make this convenient enum class Fruit(@StringRes val stringRes: Int) { Apple(R.string.fruit_apple), Oranges(R.string.fruit_orange) } When we want to consume this enum from a Restful API with a Moshi converter, Moshi automatically generates the enum adapter for you, but if you want to customise the behaviour for whatever reason, you can do object FruitsAdapter { @ToJson fun toJson(type: Fruit): String = type.name @FromJson fun fromJson(name: String): Fruit = Fruit.values().first { it.name == name } } Happy days. Everything is working as expected. When things go bananascom.squareup.moshi.JsonDataException: Expected one of [Apple, Oranges] but was Bananas at path $ Good APIs don't break contracts. Not all APIs are good APIs, so some can break contracts. What do we do now? push out an update with added enum value and its string resource? Perhaps we can make use of EnumJsonAdapter's .withUnknownFallBack() enum class Fruit(@StringRes val stringRes: Int) { Apple(R.string.fruit_apple), Oranges(R.string.fruit_orange), Unknown(R.string.fruit_unknown) } Moshi.Builder() .add(KotlinJsonAdapterFactory()) .add(Fruit::class.java, EnumJsonAdapter.create(Fruit::class.java) .withUnknownFallback(Fruit.Unknown)) .build() This certainly stops the app from crashing, but what if we actually want to show the "bananas" that the API sends? you know, as a fail safe so that users wouldn't end up seeing "unknowns". Let's open up the Enums Enums are by definition finite. Enums are final by design. Enums can't be subclassed but they still can inherit interfaces. We will exploit this to create our "unconfined" enum interface Fruit { val name: String data class Unknown(override val name: