title: Moshi with duplicate fields
body: <p>I've got a json response that looks like this for some cases:</p>
  
  <pre><code>{
        "id" : 12345,
        "events": [
           {
              "desc": "Bla bla"
               ...
           }, 
           {
              "desc": "Yada yada",
              ...
           },
         ]
  
      }
  </code></pre>
  
  <p>Whilst for some other scenarios it looks like this:</p>
  
  <pre><code>{
    "id" : 12345,
    "events": {
       "desc": "Bla bla"
       ...
    },
    "events" : {
      "desc": "Yada yada"
      ...
    },
  }
  </code></pre>
  
  <p>That is, sometimes <code>events</code> will be an array, sometimes <code>events</code> is duplicated with multiple values. This throws the following exception using moshi + retrofit:</p>
  
  <pre><code>    2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp: Multiple values for 'events' at $[0].events
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp: com.squareup.moshi.JsonDataException: Multiple values for 'events' at $[0].events
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapter.fromJson(KotlinJsonAdapter.kt:80)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at com.squareup.moshi.CollectionJsonAdapter.fromJson(CollectionJsonAdapter.java:76)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at com.squareup.moshi.CollectionJsonAdapter$2.fromJson(CollectionJsonAdapter.java:53)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:40)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:45)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at retrofit2.converter.moshi.MoshiResponseBodyConverter.convert(MoshiResponseBodyConverter.java:27)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
  2019-12-30 13:58:20.458 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:45)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Observable.subscribe(Observable.java:11194)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Observable.subscribe(Observable.java:11194)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.observable.ObservableSingleSingle.subscribeActual(ObservableSingleSingle.java:35)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleFlatMap$SingleFlatMapCallback.onSuccess(SingleFlatMap.java:84)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleDoOnSuccess$DoOnSuccess.onSuccess(SingleDoOnSuccess.java:59)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:56)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleDoOnSuccess.subscribeActual(SingleDoOnSuccess.java:35)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:36)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.459 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleMap.subscribeActual(SingleMap.java:34)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleFlatMap.subscribeActual(SingleFlatMap.java:36)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleDoOnSuccess.subscribeActual(SingleDoOnSuccess.java:35)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Single.subscribe(Single.java:3096)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Flowable.subscribe(Flowable.java:13234)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Flowable.subscribe(Flowable.java:13180)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.flowable.FlowableZip$ZipCoordinator.subscribe(FlowableZip.java:127)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.flowable.FlowableZip.subscribeActual(FlowableZip.java:79)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Flowable.subscribe(Flowable.java:13234)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:38)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Flowable.subscribe(Flowable.java:13234)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.flowable.FlowableOnErrorReturn.subscribeActual(FlowableOnErrorReturn.java:33)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Flowable.subscribe(Flowable.java:13234)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.Flowable.subscribe(Flowable.java:13180)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  2019-12-30 13:58:20.460 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  2019-12-30 13:58:20.461 21419-21419/com.myapp.android.debug E/DetailFragment$loadUp:     at java.lang.Thread.run(Thread.java:764)
  </code></pre>
  
  <p>I'd like to standardize the output for both scenarios, that is, I would like to turn this into</p>
  
  <pre><code>data class Parcel(val events: List&lt;Event&gt;)
  </code></pre>
  
  <p>I know the second kind of response is malformed but I have no control over the backend (its an external service that im consuming), is there a way to fix this?</p>
  
  <p>I tried fiddling with custom adapters but i cant make heads or tails of how to do it :(</p>
  
  <p>EDIT: My best attempt at a Custom Adapter:</p>
  
  <pre><code>class CorreosApiParcelAdapter(private val eventAdapter: JsonAdapter&lt;CorreosApiEvent&gt;,
                                private val errorAdapter: JsonAdapter&lt;Error&gt;) : JsonAdapter&lt;CorreosApiParcel&gt;() {
      override fun fromJson(reader: JsonReader): CorreosApiParcel? = with(reader) {
          val events = mutableListOf&lt;CorreosApiEvent&gt;()
          val parcel = CorreosApiParcel.allNull()
          beginObject()
          while (hasNext()) {
              val nextName = nextName()
              if (nextName != "eventos" &amp;&amp; nextName != "error") {
                  val value = reader.nextString()
                  when (nextName) {
                      "codEnvio" -&gt; parcel.codEnvio = value
                      "refCliente" -&gt; parcel.refCliente = value
                      "codProducto" -&gt; parcel.codProducto = value
                      "fecha_calculada" -&gt; parcel.fechaCalculada = value
                      "largo" -&gt; parcel.largo = value
                      "ancho" -&gt; parcel.ancho = value
                      "alto" -&gt; parcel.alto = value
                      "peso" -&gt; parcel.peso = value
                  }
                  continue
              }
              if (nextName == "error") {
                  val error = errorAdapter.fromJson(reader)
                  if (error != null) {
                      parcel.error = error
                  }
                  continue
              }
  
              if (peek() == JsonReader.Token.BEGIN_OBJECT) {
                  val fromJson = eventAdapter.fromJson(reader)
                  if (fromJson != null) {
                      events += fromJson
                  }
                  continue
              }
              beginArray()
              while (hasNext()) {
                  val fromJson = eventAdapter.fromJson(reader)
                  if (fromJson != null) {
                      events += fromJson
                  }
              }
              endArray()
  
          }
          endObject()
          return parcel
      }
  
  
      override fun toJson(writer: JsonWriter, value: CorreosApiParcel?) {
      }
  
      companion object {
          val FACTORY: JsonAdapter.Factory = Factory { type, _, moshi -&gt;
  
  
              if (Types.getRawType(type) != CorreosApiParcel::class.java)
                  return@Factory null
  
              val eventAdapter = moshi.adapter&lt;CorreosApiEvent&gt;(CorreosApiEvent::class.java)
              val errorAdapter = moshi.adapter&lt;Error&gt;(Error::class.java)
              return@Factory CorreosApiParcelAdapter(eventAdapter, errorAdapter)
          }
      }
  }
  </code></pre>