Джексон JsonIgnore не работает в kotlin - PullRequest
0 голосов
/ 12 марта 2020

Я переписываю Java Приложение Spring для Kotlin Приложение Spring.

Все отлично работает, кроме API-запроса к openweather.

Для хранения DTO в базе данных есть поле id вместе с cityId, полученным из API (там оно называется id).

По какой-то причине @JsonIgnore не работает для Поле идентификатора DTO.

build.gradle

// plugins

    id 'org.springframework.boot' version '2.2.4.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
    id 'war'
    id 'maven'
    id 'org.jetbrains.kotlin.jvm' version '1.3.70'
    id "org.jetbrains.kotlin.plugin.jpa" version "1.3.70"
    id "org.jetbrains.kotlin.plugin.noarg" version "1.3.70"
    id "org.jetbrains.kotlin.plugin.spring" version "1.3.70"
    id "org.jetbrains.kotlin.plugin.allopen" version "1.3.70"


// dependencies

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-mail:2.2.4.RELEASE'
    implementation 'org.springframework.security:spring-security-test'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    implementation "org.jetbrains.kotlin:kotlin-reflect"
    implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.10.2"

OpenWeather отвечает следующим JSON (некоторые поля опущены):

{
    "coord":{
        "lon":-0.13,
        "lat":51.51
    },
    "main":{
        "temp":14.04,
        "feels_like":7.05,
        "pressure":1011,
        "humidity":61
    },
    "dt":1584018901,
    "id":2643743,              <- cityId in DTO class
    "name":"London",
 ...
}

Класс DTO:


import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonProperty

@JsonIgnoreProperties(ignoreUnknown = true)
data class OpenWeatherApiDto(
        @JsonIgnore
        override var id: Long? = null,
        ...
        override var cityId: Int? = null,
        ...
) : AbstractWeatherSampleDto() {
    ...
    @JsonProperty("id")
    private fun unpackId(idObj: Int?) {
        cityId = idObj
                ?: throw ApiFieldNotFoundException("id")
    }
    ...
}

Сбой теста

@Test
    fun createFromFile() {
        val mapper = jacksonObjectMapper()
        Files.lines(Paths.get("src/test/resources/data/OWApi.json")).use { s ->
            val json: String = s.collect(Collectors.joining())
            val ws: OpenWeatherApiDto = mapper.readValue(json)
            println(ws)
            assertThat(ws)
                    .isNotNull
                    .extracting("cityId").isEqualTo(2643743)
        }
    }

Сообщение об ошибке:

[Extracted: cityId] 
Expecting:
 <null>
to be equal to:
 <2643743>
but was not.

И фактический объект:

OpenWeatherApiDto ( id = 2643743 , cityName = Лондон, температура = 14,04, feelsLike = 7,05, давление = 1011,0, влажность = 61, облака = ноль, cityId = ноль , время = 1584018901, широта = 51,51, долгота = -0.13)

Я обнаружил похожую проблему на jackson-module-kotlin странице GitHub , которая оказалась jackson-databind связанной и решена in 2.9.6 пока я использую 2.10.2

1 Ответ

0 голосов
/ 12 марта 2020

Я не пробовал использовать именно те версии, которые вы используете, но я подозреваю, что это сработает, если вы замените @JsonIgnore на @get:JsonIgnore.

Это одна из тех распространенных ошибок при конвертации Java в Kotlin. В Java вы обычно реализуете свойство с закрытым полем и методом получения (и установщиком, если оно изменчиво). Вы также можете включить параметр конструктора для его инициализации. Это до четырех отдельных битов кода, каждый из которых связан с одним и тем же свойством - и каждый может иметь свои собственные аннотации.

Однако в Kotlin вы можете получить их все из одного бита кода. (Любое не приватное свойство дает вам приватное поле и метод получения; если оно равно var, вы также получаете установщик; и если оно находится в первичном конструкторе, то вы также получаете параметр конструктора.) Что гораздо лаконичнее!

Но к чему применяются какие-либо аннотации?

По умолчанию они применяются к параметру конструктора - или, если свойство определено в теле класса, к самому свойству (которое видно только для Kotlin). Поэтому, если вы хотите, чтобы они применялись к полю, или к получателю или установщику, вам нужно указать это явно, например, @field:JsonIgnore или @get:JsonIgnore.

Полная информация содержится в Kotlin документы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...