Search code examples
androidretrofit2android-jetpack-compose

Unable to get data from Retrofit Call to a Direct JSON File


I am working on small project on a Jetpack Compose. I am trying to data from a static JSON File from this url using Retrofit. https://firebasestorage.googleapis.com/v0/b/culoader.appspot.com/o/json%2Fcudata.json?alt=media&token=d0679703-2f6c-440f-af03-d4d61305cc84

Network Module

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun proveidesCurrencyService() : CurrencyService{
        return Retrofit.Builder()
            .baseUrl("https://firebasestorage.googleapis.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(CurrencyService::class.java)
    }
}

Service Class

interface CurrencyService {
    //@Streaming
    @GET
    suspend fun getCurrencyFile(@Url fileUrl:String): Response<ResponseBody>

}


data class CurrencyAPIResponse(

    @SerializedName("data") var data: MutableState<List<CurrencyRates>>

)

data class CurrencyRates (

    @SerializedName("code") var code : String,
    @SerializedName("value") var value : String

)

ViewModel


@HiltViewModel
class CurrencyDataViewModel
@Inject
constructor(private val currencyService: CurrencyService
) : ViewModel() 
{
 init {
        getCurrencyFileData()
    }
}

 fun getCurrencyFileData() = viewModelScope.launch(Dispatchers.IO) {
        val url: String =
            "https://firebasestorage.googleapis.com/v0/b/culoader.appspot.com/o/json%2Fcudata.json?alt=media&token=d0679703-2f6c-440f-af03-d4d61305cc84"

        val responseBody = currencyService.getCurrencyFile(url).body()
        if (responseBody != null) {
            Log.d("\nresponsebody", responseBody.string())
            val gson = GsonBuilder().setPrettyPrinting().create()
            val currencyAPIResponse = gson.fromJson(responseBody.string(), CurrencyAPIResponse::class.java)
            val data: MutableState<List<CurrencyRates>> = currencyAPIResponse.data
            Log.d("Data", data.value[0].code)

        }

    }

Everytime, I am getting the below error,

Attempt to invoke virtual method 'androidx.compose.runtime.MutableState com.tuts.playlite.network.response.CurrencyAPIResponse.getData()' on a null object reference

Not sure, where I am failing, I have tried to convert this to JSON Object, but still failing. Is it right way to get the data?

Another thing noticed that even though the JSON file is complete in the url, the response body log is showing the JSON with some other content.

{
          "code": "IMP",
          "value": "0.722603"
        },
        {
          "code": "INR",
    
    [          1631385414.170 12452:12478 D/
     responsebody]
          "value": "72.99465"
        },
        {
          "code": "IQD",
          "value": "1458.61356"
        },

As a result, the GSON might not able to form the json and hence could be getting null exception. Not sure why random text is getting added!


Solution

  • Finally, the culprit seems to be responseBody Stream. After I changed the code with below, It seems to be working. I assume, it was unable to get the proper complete JSON earlier and throwing the null object reference error.

        val responseBody = currencyService.getCurrencyFile(url).body()
        val resData = responseBody?.byteStream()!!.bufferedReader().use {
            it.readText()
        }
        val gson = GsonBuilder().setPrettyPrinting().create()
        val currencyAPIResponse = gson.fromJson(resData, CurrencyAPIResponse::class.java)
    

    Thank you for all support!