jsonmoshi

How to deserialize JSON enums in case insensitive way using Moshi library?


The sample source JSON object is defined as:

{
  "source": "WIFI"
}

However, the value can be lowercase and when it does, I get following error.

Exception in thread "main" com.squareup.moshi.JsonDataException: 
Expected one of [WIFI, CELL, GPS] but was 'wifi' at path $.locations[1].source

There there known annotation or out of box solution to convert lowercase to upper case enum?

I am looking at the https://github.com/square/moshi/blob/master/moshi-adapters/src/main/java/com/squareup/moshi/adapters/EnumJsonAdapter.kt to see if that can be modified for this.


Solution

  • I was able to modify the EnumJsonAdapter to handle lower or upper case JSON coming from the response by some modification.

    Here is snippet of it

    // From fun fromJson(reader: JsonReader): T? 
    
    if(useCaseInsensitiveName) {
      val name = reader.nextString()
      // Find if `name` is in the `nameStrings` array in case-insensitive manner
      val itemIndex = nameStrings.indexOfFirst { it.equals(name, ignoreCase = true) }
      if (itemIndex != -1) {
        return constants[itemIndex]
      }
      return fallbackValue
    } else {
      reader.skipValue()
      return fallbackValue
    }
    

    That seems to work well from both ways UPPER_CASE / lower_case \ MIXED_case


    Here is the modified file with the full change.

    Usage after modification

    Moshi.Builder()
      .add(
        LocationRecordSource::class.java,
            EnumCustomJsonAdapter.create(LocationRecordSource::class.java).withUnknownFallback(
              fallbackValue = LocationRecordSource.UNKNOWN,
              useCaseInsensitiveName = true,
            ),
          )
      .build()