Home > Enterprise >  Im try to retrieve some data from api OpenWeatherApp im using Kotlin Expected BEGIN_ARRAY but was BE
Im try to retrieve some data from api OpenWeatherApp im using Kotlin Expected BEGIN_ARRAY but was BE

Time:01-09

Im try to retrieve some data from api OpenWeatherApp im using Kotlin but i got this error:

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

i need to know how can i call the json_object instead the json_array

Adapter

class WeatherAdapter (
var weather: List<Weather>)
: RecyclerView.Adapter<WeatherAdapter.ViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val binding = WeatherItemBinding.inflate(
        LayoutInflater.from(parent.context),
        parent,
        false
    )
    return ViewHolder(binding)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val weather = weather[position]
    holder.bind(weather)
}

override fun getItemCount() = weather.size

class ViewHolder(private val binding: WeatherItemBinding):
    RecyclerView.ViewHolder(binding.root) {

    fun bind(weatherInfo: Weather) {

        binding.weatherName.text = weatherInfo.name
        binding.weatherName.text = weatherInfo.base
        binding.weatherName.text = weatherInfo.wind.speed.toString()

    }
  }
}

Activity

open class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val binding = ActivityMainBinding.inflate(layoutInflater)

    setContentView(binding.root)

    val weatherAdapter = WeatherAdapter(emptyList())

    binding.recycler.adapter = weatherAdapter



    lifecycleScope.launch {
        val weather = WeatherDbClient.service?.listWeatherApp()
        val body = withContext(Dispatchers.IO) {
            weather?.execute()?.body()
        }

        if(body != null){
            weatherAdapter.weather = body
            weatherAdapter.notifyDataSetChanged()

        }
      }
    }
}

interface

interface WeatherService {

    @GET("weather?APPID=$API_KEY&q=$CITY_WEATHER")
    fun listWeatherApp(): Call<List<Weather>>

}

Objetct

object WeatherDbClient {
    private val interceptor = 
    HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)

    private val http = OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .build()


    private val retrofit = Retrofit.Builder()
        .baseUrl(URL_BASE)
        .addConverterFactory(GsonConverterFactory.create())
        .client(http)
        .build()

    val service: WeatherService? = retrofit.create(WeatherService::class.java)

}

CodePudding user response:

that's error happens to me twice

  • if there's an null value from api
  • if the corresponding datatype is not match the api value data type for example : id:Int maybe that's will got this error because the api value is huge number and we should use BigDecimal datatype

CodePudding user response:

I guess your response models are wrong. Try the following models:

data class WeatherResponse (
  @SerializedName("weather") var weather: ArrayList<Weather> = arrayListOf(),
  @SerializedName("base") var base: String? = null,
  @SerializedName("main") var main: Main? = Main(),
  @SerializedName("visibility") var visibility : Int? = null,
  @SerializedName("wind") var wind: Wind? = Wind(),
  @SerializedName("clouds") var clouds: Clouds? = Clouds(),
  @SerializedName("dt") var dt: Int? = null,
  @SerializedName("sys") var sys: Sys? = Sys(),
  @SerializedName("id") var id: Int? = null,
  @SerializedName("name") var name: String? = null,
  @SerializedName("cod") var cod: Int? = null
)

data class Weather (

  @SerializedName("id"          ) var id          : Int?    = null,
  @SerializedName("main"        ) var main        : String? = null,
  @SerializedName("description" ) var description : String? = null,
  @SerializedName("icon"        ) var icon        : String? = null

)

data class Main (

  @SerializedName("temp"     ) var temp     : Double? = null,
  @SerializedName("pressure" ) var pressure : Int?    = null,
  @SerializedName("humidity" ) var humidity : Int?    = null,
  @SerializedName("temp_min" ) var tempMin  : Double? = null,
  @SerializedName("temp_max" ) var tempMax  : Double? = null

)

data class Wind (

  @SerializedName("speed" ) var speed : Double? = null,
  @SerializedName("deg"   ) var deg   : Int?    = null

)

data class Clouds (

  @SerializedName("all" ) var all : Int? = null

)

data class Sys (

  @SerializedName("type"    ) var type    : Int?    = null,
  @SerializedName("id"      ) var id      : Int?    = null,
  @SerializedName("message" ) var message : Double? = null,
  @SerializedName("country" ) var country : String? = null,
  @SerializedName("sunrise" ) var sunrise : Int?    = null,
  @SerializedName("sunset"  ) var sunset  : Int?    = null

)

And the request should be:

interface WeatherService {

    @GET("weather?APPID=$API_KEY&q=$CITY_WEATHER")
    fun listWeatherApp(): Call<WeatherResponse>

}

NOTE: there is a handy JSON converter to Kotlin Data Classes.

  •  Tags:  
  • Related