Jos*_*bre 18 android jackson kotlin retrofit2
我正在尝试使用API进行改型和杰克逊反序列化。标题“没有创建者,就像默认构造一样,存在”中出现的错误:无法从对象值反序列化(没有基于委托人或基于属性的创建者)出现在onFailure中。
这是我要获取的JSON:
{
"data": {
"repsol_id": "1129",
"name": "ES-MASSAMÁ",
"latitude": "38.763733333",
"longitude": "-9.258619444000001",
"address": "RUA GENERAL HUMBERTO DELGADO, LT.16",
"post_code": "2745-280",
"location": "QUELUZ",
"service_store": 1,
"service_mechanical_workshop": 0,
"service_restaurant": 0,
"service_wash": 1
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的HomeFragment:
onCreate(){
viewModel.retrieveStation().observe(this, Observer {
dataBinding.favouriteStationTxt.text = it.name
})
}
Run Code Online (Sandbox Code Playgroud)
这是我的viewModel:
class HomeViewModel @Inject constructor(
private val stationRepository: StationRepository
) : ViewModel() {
private val station = MutableLiveData<Station>()
fun retrieveStation():LiveData<Station> = station
fun loadStations(stationId:Int){
stationRepository.getStationFromId(stationId,{ station.postValue(it)},{})
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的存储库:
class StationRepository @Inject constructor(var apiManager: ApiManager) {
fun getStationFromId(stationId:Int,onSuccess: (Station)->Unit, onError: (Exception)->Unit){
apiManager.getStation(stationId, onSuccess,onError)
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的API管理器(加入了多个API管理器)
class ApiManager @Inject constructor(
private val stationsApiManager: StationsApiManager,
){
fun getStation(stationId: Int, onSuccess: (Station)->Unit, onFailure: (e: Exception)->Unit){
stationsApiManager.getStation(stationId,{onSuccess(it.data.toDomain())},onFailure)
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的StationAPiManager
class StationsApiManager @Inject constructor(private val stationApiService: StationsApiService){
fun getStation(stationId: Int, onSuccess: (StationResponse)->Unit, onFailure: (e: Exception)->Unit){
stationApiService.getStation(stationId).enqueue(request(onSuccess, onFailure))
}
private fun <T> request(onSuccess: (T)->Unit, onFailure: (e: Exception)->Unit)= object : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
Log.d("error",t.message)
onFailure(Exception(t.message))
}
override fun onResponse(call: Call<T>, response: Response<T>) {
Log.d("Success",response.body().toString())
if(response.isSuccessful && response.body() != null) onSuccess(response.body()!!)
else
onFailure(Exception(response.message()))
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的STationsApiService(基本URL在口味中)
@GET("{station_id}")
fun getStation(@Path("station_id") stationId: Int): Call<StationResponse>
Run Code Online (Sandbox Code Playgroud)
这是我的StationResponse
class StationResponse (
@JsonProperty("data")
val data: Station)
Run Code Online (Sandbox Code Playgroud)
这是我的Station模型
data class Station(
val repsol_id: String,
val name: String,
val latitude: String,
val longitude: String,
val address: String,
val post_code: String,
val location: String,
val service_store: Boolean,
val service_mechanical_workshop: Boolean,
val service_restaurant: Boolean,
val service_wash: Boolean
)
Run Code Online (Sandbox Code Playgroud)
这是我的DataMappers:
import com.repsol.repsolmove.network.movestationsapi.model.Station as apiStation
fun apiStation.toDomain() = Station(
repsol_id.toInt(),
name,
latitude.toDouble(),
longitude.toDouble(),
address,
post_code,
location,
service_store,
service_mechanical_workshop,
service_restaurant,
service_wash
)
Run Code Online (Sandbox Code Playgroud)
Bek*_*Bek 97
原因:发生此错误是因为jackson library不知道如何创建没有的模型,empty constructor并且模型包含的构造函数的参数未使用@JsonProperty("field_name"). 默认情况下,如果您没有向类添加构造函数,java 编译器会创建空的构造函数。
解决方案:
添加empty constructor到您的模型或注释构造函数参数@JsonProperty("field_name")
如果你使用kotlin data classthen 也可以注释@JsonProperty("field_name")或注册jackson 模块 kotlin到ObjectMapper.
您可以使用http://www.jsonschema2pojo.org/创建模型。
小智 46
如果您在POJO 模型上使用Lombok,请确保您有以下注释:
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
Run Code Online (Sandbox Code Playgroud)
它可能会有所不同,但请确保@Getter,尤其是@NoArgsConstructor。
Yon*_*bbs 20
您需要使用jackson-kotlin-module反序列化数据类。有关详细信息,请参见此处。
上述错误信息是什么杰克逊给你,如果你尝试反序列化某个值到数据类时未启用该模块,或者即使是这样,当ObjectMapper它使用没有KotlinModule注册。例如,使用以下代码:
data class TestDataClass (val foo: String)
val jsonString = """{ "foo": "bar" }"""
val deserializedValue = ObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)
Run Code Online (Sandbox Code Playgroud)
这将失败,并显示以下错误:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `test.SerializationTests$TestDataClass` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
Run Code Online (Sandbox Code Playgroud)
如果您更改上面的代码并替换ObjectMapper为jacksonObjectMapper(仅返回ObjectMapper已KotlinModule注册的普通代码),则它可以工作。即
val deserializedValue = jacksonObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)
Run Code Online (Sandbox Code Playgroud)
我不确定Android方面的问题,但看起来您需要让系统使用jacksonObjectMapper进行反序列化。
Mic*_*lPr 20
我正在使用 Quarkus、Jackson 和 Lombok。所以我通过@Jacksonized在模型类上添加属性来解决这个问题。所以所有属性都是:
@Jacksonized //missing
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ...
Run Code Online (Sandbox Code Playgroud)
Fed*_*ika 12
我在这里搜索此错误:
No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator
Run Code Online (Sandbox Code Playgroud)
与Retrofit无关,但是如果您使用的是Jackson,则可以通过向引发错误的类中添加默认构造函数来解决此错误。此处更多信息:https : //www.baeldung.com/jackson-exception
小智 9
我知道这是一篇旧帖子,但对于任何使用 Retrofit 的人来说,这可能很有用。
如果你使用 Retrofit + Jackson + Kotlin + Data 类,你需要:
implement group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.7.1-2'到您的依赖项中,以便 Jackson 可以反序列化为 Data 类 val jsonMapper = com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()
val retrofit = Retrofit.Builder()
...
.addConverterFactory(JacksonConverterFactory.create(jsonMapper))
.build()
Run Code Online (Sandbox Code Playgroud)
注意:如果没有使用 Retrofit,@Jayson Minard 有一个更通用的方法答案。
如果使用的话lombok可以使用@Jacksonized注释。
您不需要设置器 - 此注释可以很好地与@Value.
你不需要@NoArgsConstructor- 你可以使用@Builder或 只是@RequiredArgsConstructor.
我通过添加无参数构造函数解决了这个问题。如果您使用的是Lombok,则只需要添加@NoArgsConstructor注释:
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
public class User {
private Long userId;
private String shortName;
}
Run Code Online (Sandbox Code Playgroud)
小智 6
我正在 Kotlin 中使用rescu并使用 @ConstructorProperties 解决它
data class MyResponse @ConstructorProperties("message", "count") constructor(
val message: String,
val count: Int
)
Run Code Online (Sandbox Code Playgroud)
杰克逊使用@ConstructorProperties。这也应该修复 Lombok @Data 。
我有一个类似的问题(使用 Jackson、lombok、gradle)和一个没有 args 构造函数的 POJO - 解决方案是添加
lombok.anyConstructor.addConstructorProperties=true
Run Code Online (Sandbox Code Playgroud)
到lombok.config文件
| 归档时间: |
|
| 查看次数: |
41866 次 |
| 最近记录: |