I'm using Jackson to deserialize Json responses from Retrofit.
I use the Jackson Module Kotlin library for that.
I have data classes with default values for some values that Java represents as primitives, so it won't crash when accessing it without null check.
This all works fine in debug
mode, but when I run on release
with proguard enabled, default values are not set and those values are null, causing my app to crash when accessing them from Java assuming primitives.
I've tried to add every proguard rule I could find online, but with no success.
If anyone has any idea, please share.
Thanks
Example of a data class
data class RideTask(@JsonProperty(RiderFrontendConsts.PARAM_LOCATION)
val location: UserVisibleLocation?,
@JsonProperty(RiderFrontendConsts.PARAM_ETA_TS)
val etaTime: Double?,
@JsonProperty(RiderFrontendConsts.PARAM_TIME_TO_COMPLETION)
val timeToCompletion: Double?,
@JsonProperty(RiderFrontendConsts.PARAM_ETA_DESCRIPTION)
val etaDescription: String?,
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonProperty(RiderFrontendConsts.PARAM_INTERNAL_ETA_TS)
val internalEta: Long? = 0,
@JsonProperty(RiderFrontendConsts.PARAM_ETA_DESCRIPTION_LIST)
val etaDescriptionList: List<String>?,
@JsonProperty(RiderFrontendConsts.PARAM_DESCRIPTION_PREFIX)
val descriptionPrefix: String?,
@JsonProperty(RiderFrontendConsts.PARAM_WALKING_DISTANCE_DESCRIPTION)
val walkingDistanceDescription: String?,
@JsonProperty(RiderFrontendConsts.PARAM_WALKING_DISTANCE_IN_METERS)
val walkingDistanceInMeters: Int? = 0)
: Serializable
Retrofit and Jackson initialisation
private Retrofit getRetrofit() {
LOGGER.debug("prepare retrofit");
return new Retrofit.Builder()
.client(getHttpClient(RiderFrontendConsts.DEFAULT_TIMEOUT_IN_MILLIS))
.baseUrl(SettingsManager.getInstance(Application.getInstance()).getServerBaseUrl())
.addConverterFactory(JacksonConverterFactory.create(getObjectMapper()))
.callbackExecutor(Executors.newCachedThreadPool())
.build();
}
private static ObjectMapper getObjectMapper() {
LOGGER.debug("prepare object mapper");
return ExtensionsKt.jacksonObjectMapper()
.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX)
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY)
.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);
}
Related pro guard rules
#parsers
-keep class com.fasterxml.jackson.annotation.** { *; }
-dontwarn com.fasterxml.jackson.databind.**
# Kotlin
-keep class kotlin.Metadata { *; }
-keepclassmembers public class via.rider.frontend.** {
public synthetic <methods>;
}
val mapper = ObjectMapper().registerKotlinModule()
extension function from there. Hope this helps. – Oleg