Kanadista
Kanadista

Reputation: 31

Can't receive byte array using Retrofit 2 in Kotlin

I have a DTO class using Moshi that's supposed to send and receive byte arrays[], but it only works when sending them, because when I receive then I have this exception.

com.squareup.moshi.JsonDataException: Expected BEGIN_ARRAY but was STRING at path $[0].image

But im pretty sure that the type that the API returns is a byte array.

Here's the DTO class and API controller

@JsonClass(generateAdapter = true)
data class LocationImageDTO (
    @Json(name="idLocationImage") val idLocationImage: Int,
    @Json(name = "idLocation") val idLocation: Int?,
    @Json(name="image") val image: ByteArray,
)


//This one is for recieving
        public List<clsLocationImage> getList(int idLocation)
        {
            List<clsLocationImage> list = new List<clsLocationImage>();
            clsLocationImage locationImage;

            clsMyConnection connection = new clsMyConnection();

            SqlCommand command = new SqlCommand
            {
                CommandText = "SELECT idLocationImage, idLocation, image FROM K0_MAP_LOCATION_IMAGES WHERE idLocation = @idLocation",

                Connection = connection.getConnection()

            };

            command.Parameters.Add("@idLocation", System.Data.SqlDbType.Int).Value = idLocation;
            SqlDataReader reader;

            try
            {

                reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        locationImage = new clsLocationImage();

                        locationImage.idLocationImage = (int)reader["idLocationImage"];
                        locationImage.idLocation = (int)reader["idLocation"];
                        locationImage.image = (byte[])reader["image"];
              
                        list.Add(locationImage);

                    }
                }
            }
            catch (SqlException excepcion)
            {

                throw excepcion;
            }

            return list;
        }


        public List<clsLocationImage> getListDAL(int id)
        {
            return getList(id);
        }

    }
}


///This one is for sending
        public int createLocationImage(clsLocationImage locationImage)
        {
            int filasAfectadas = 0;

            clsMyConnection conexion = new clsMyConnection();

            SqlCommand miComando = new SqlCommand
            {

                CommandText = "INSERT INTO K0_MAP_LOCATION_IMAGES(idLocation, image) VALUES (@idLocation, @image)",

                Connection = conexion.getConnection()

            };

            miComando.Parameters.Add("@idLocation", System.Data.SqlDbType.Int).Value = locationImage.idLocation;
            miComando.Parameters.Add("@image", System.Data.SqlDbType.VarBinary).Value = locationImage.image;

            try
            {
                filasAfectadas = miComando.ExecuteNonQuery();

            }

            catch (SqlException excepcion)
            {

                throw excepcion;

            }

            return filasAfectadas;
        }
    }
}

Upvotes: 0

Views: 545

Answers (1)

Kanadista
Kanadista

Reputation: 31

You need to set an explicit JSON adapter to the Moshi Builder.


class CustomDateAdapter : JsonAdapter<Date>() {
    private val dateFormat = SimpleDateFormat(SERVER_FORMAT, Locale.getDefault())

    @FromJson
    override fun fromJson(reader: JsonReader): Date? {
        return try {
            val dateAsString = reader.nextString()
            synchronized(dateFormat) {
                dateFormat.parse(dateAsString)
            }
        } catch (e: Exception) {
            null
        }
    }

    @ToJson
    override fun toJson(writer: JsonWriter, value: Date?) {
        if (value != null) {
            synchronized(dateFormat) {
                writer.value(value.toString())
            }
        }
    }

    companion object {
        const val SERVER_FORMAT = ("yyyy-MM-dd'T'HH:mm") // define your server format here
    }
}

And then you add it in the Moshi builder

 private val moshiBuilder = Moshi.Builder().add(CustomDateAdapter())

        private fun getRetrofit(): Retrofit =
            Retrofit.Builder()
                .baseUrl(MAPK0_API_BASE_URL)
                .addConverterFactory(MoshiConverterFactory.create(moshiBuilder.build()))
                //.client(getUnsafeOkHttpClient())
                .build()
    }

Upvotes: 0

Related Questions