0

When communicating with some APIs, it can happen that the JSON body may have duplicate fields which can cause the following error:

com.squareup.moshi.JsonDataException: Multiple values for 'name' at $.person.name

This can happen when the API delivers something similar to as follows:

{
  "name" : "Chuck",
  "age" : 21,
  "name" : "Chuck"
}

How to handle such an issue?

I tried researching the web to see what I can find and found a similar answer here which handles duplicate data as a list and adding it together, but not showing a simple way as to how to ignore or overwrite it.

There is also confirmation that Moshi does not support this yet or may not even support it in the future as it is more of an issue with the API and not Moshi

LethalMaus
  • 798
  • 1
  • 8
  • 20
  • 1
    It's not supported and I doubt it will be supported since the RFC 4627 says: 'The names within an object SHOULD be unique' https://www.ietf.org/rfc/rfc4627.txt?number=4627 – Stephan Nov 09 '22 at 13:35
  • Does this answer your question? [Moshi with duplicate fields](https://stackoverflow.com/questions/59531299/moshi-with-duplicate-fields) – Stephan Nov 09 '22 at 13:35
  • No Stephan, the link is also referenced in the question and is more towards handling the duplicate in the sense of ignoring/overwriting it – LethalMaus Nov 09 '22 at 13:38

1 Answers1

0

After some trial and error, the current solution for me is as follows:

Create an adapter specific to the data class that may be affected with duplicate fields

object PersonAdapter {
    @FromJson
    fun fromJson(reader: JsonReader) = with(reader) {
        var name: String? = null
        var age: Int? = null
        beginObject()
        while(hasNext()) {
            try {
                when (reader.nextName()) {
                    "name" -> name = nextString()
                    "age" -> age = nextInt()
                    else -> reader.skipValue()
                }
             catch (e: Exception) {
                 //This can happen when getNextString etc is null
                 reader.skipValue()
             }
        }
        endObject()
        Person(name, age)
    }
}

Add the adapter to Moshi. This only worked for me when the adapter was added before KotlinJsonAdapterFactory

Moshi.Builder()
    .add(PersonAdapter)
    .add(KotlinJsonAdapterFactory())
    .build()
LethalMaus
  • 798
  • 1
  • 8
  • 20