All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.apollographql.apollo.api.internal.ResponseParser.kt Maven / Gradle / Ivy

The newest version!
package com.apollographql.apollo.api.internal

import com.apollographql.apollo.annotations.ApolloInternal
import com.apollographql.apollo.api.ApolloResponse
import com.apollographql.apollo.api.CustomScalarAdapters
import com.apollographql.apollo.api.DeferredFragmentIdentifier
import com.apollographql.apollo.api.Error
import com.apollographql.apollo.api.Operation
import com.apollographql.apollo.api.falseVariables
import com.apollographql.apollo.api.json.JsonReader
import com.apollographql.apollo.api.json.MapJsonReader
import com.apollographql.apollo.api.json.readAny
import com.apollographql.apollo.api.parseData
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4

/**
 * [ResponseParser] parses network responses, including data, errors and extensions from a [JsonReader]
 */
internal object ResponseParser {
  fun  parse(
      jsonReader: JsonReader,
      operation: Operation,
      requestUuid: Uuid?,
      customScalarAdapters: CustomScalarAdapters,
      deferredFragmentIds: Set?,
  ): ApolloResponse {
    jsonReader.beginObject()

    var data: D? = null
    var errors: List? = null
    var extensions: Map? = null
    while (jsonReader.hasNext()) {
      @Suppress("UNCHECKED_CAST")
      when (jsonReader.nextName()) {
        "data" -> {
          val falseVariables = operation.falseVariables(customScalarAdapters)
          data = operation.parseData(jsonReader, customScalarAdapters, falseVariables, deferredFragmentIds, errors)
        }
        "errors" -> errors = jsonReader.readErrors()
        "extensions" -> extensions = jsonReader.readAny() as? Map
        else -> jsonReader.skipValue()
      }
    }

    jsonReader.endObject()

    return ApolloResponse.Builder(operation = operation, requestUuid = requestUuid ?: uuid4())
        .errors(errors)
        .data(data)
        .extensions(extensions)
        .build()
  }

  fun parseError(
      payload: Map,
  ) = MapJsonReader(payload).readError()
}

@Suppress("UNCHECKED_CAST")
private fun JsonReader.readError(): Error {
  var message = ""
  var locations: List? = null
  var path: List? = null
  var extensions: Map? = null
  var nonStandardFields: MutableMap? = null
  beginObject()
  while (hasNext()) {
    when (val name = nextName()) {
      "message" -> message = nextString() ?: ""
      "locations" -> {
        locations = readErrorLocations()
      }

      "path" -> {
        path = readPath()
      }

      "extensions" -> {
        extensions = readAny() as? Map?
      }

      else -> {
        if (nonStandardFields == null) nonStandardFields = mutableMapOf()
        nonStandardFields[name] = readAny()
      }
    }
  }
  endObject()


  @Suppress("DEPRECATION")
  return Error(message, locations, path, extensions, nonStandardFields)
}

private fun JsonReader.readPath(): List? {
  if (peek() == JsonReader.Token.NULL) {
    return nextNull()
  }

  val list = mutableListOf()
  beginArray()
  while (hasNext()) {
    when (peek()) {
      JsonReader.Token.NUMBER, JsonReader.Token.LONG -> list.add(nextInt())
      else -> list.add(nextString()!!)
    }
  }
  endArray()

  return list
}

private fun JsonReader.readErrorLocations(): List? {
  if (peek() == JsonReader.Token.NULL) {
    return nextNull()
  }
  val list = mutableListOf()
  beginArray()
  while (hasNext()) {
    list.add(readErrorLocation())
  }
  endArray()

  return list
}

private fun JsonReader.readErrorLocation(): Error.Location {
  var line: Int = -1
  var column: Int = -1
  beginObject()
  while (hasNext()) {
    when (nextName()) {
      "line" -> line = nextInt()
      "column" -> column = nextInt()
      else -> skipValue()
    }
  }
  endObject()
  return Error.Location(line, column)
}

@ApolloInternal
fun JsonReader.readErrors(): List {
  if (peek() == JsonReader.Token.NULL) {
    nextNull()
    return emptyList()
  }

  beginArray()
  val list = mutableListOf()
  while (hasNext()) {
    list.add(readError())
  }
  endArray()
  return list
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy