Http-клиент Micronaut не распознает поля - PullRequest
0 голосов
/ 03 ноября 2019

Я получаю следующий json из службы отдыха.

{
  "AccessControlRecords": {
    "OccasionRecords": [
      {
        "Type": "",
        "BookingNr": "91376",
        "BookingRow": "1",
        "FacilityID": "OIHAL",
        "ObjectID": "STYRK",
        "PartOfObjectId": "",
        "PartOfObjectName": "",
        "FacilityName": "Odense Idrætshal",
        "ObjectName": "Styrketræningslokale",
        "BookFromDate": "17.08.2019",
        "BookToDate": "23.05.2020",
        "OccasionDate": "2020-01-04 09:00",
        "OccasionToDate": "2020-01-04 10:00",
        "FomKlo": "09:00",
        "TomKlo": "10:00",
        "TimeBefore": "0",
        "TimeAfter": "0",
        "Weekday": 0,
        "BookStatus": "",
        "KortReg": "",
        "CustomerID": "",
        "CustomerName": "Svømmeklubben Frem",
        "TypeOfBooking": "E",
        "CreatedBy": "",
        "Cards": null,
        "FunctionCode1": 0,
        "FunctionCode2": 0,
        "FunctionCode3": 0,
        "FunctionCode4": "",
        "Text1": "",
        "Text2": "",
        "Text3": "",
        "Text4": "",
        "EndUser": "",
        "Activity": "Styrketræning"
      },
      {
        "Type": "",
        "BookingNr": "90443",
        "BookingRow": "1",
        "FacilityID": "OIHAL",
        "ObjectID": "STYRK",
        "PartOfObjectId": "",
        "PartOfObjectName": "",
        "FacilityName": "Odense Idrætshal",
        "ObjectName": "Styrketræningslokale",
        "BookFromDate": "02.11.2019",
        "BookToDate": "28.03.2020",
        "OccasionDate": "2020-01-04 14:00",
        "OccasionToDate": "2020-01-04 16:30",
        "FomKlo": "14:00",
        "TomKlo": "16:30",
        "TimeBefore": "0",
        "TimeAfter": "0",
        "Weekday": 1,
        "BookStatus": "",
        "KortReg": "",
        "CustomerID": "",
        "CustomerName": "Odense Roklub",
        "TypeOfBooking": "E",
        "CreatedBy": "",
        "Cards": null,
        "FunctionCode1": 0,
        "FunctionCode2": 0,
        "FunctionCode3": 0,
        "FunctionCode4": "",
        "Text1": "",
        "Text2": "",
        "Text3": "",
        "Text4": "",
        "EndUser": "",
        "Activity": "Styrketræning"
      },
      {
        "Type": "",
        "BookingNr": "91916",
        "BookingRow": "1",
        "FacilityID": "OIHAL",
        "ObjectID": "STYRK",
        "PartOfObjectId": "DELA",
        "PartOfObjectName": "Delt styrketræning (A)",
        "FacilityName": "Odense Idrætshal",
        "ObjectName": "Styrketræningslokale",
        "BookFromDate": "24.08.2019",
        "BookToDate": "20.06.2020",
        "OccasionDate": "2020-01-04 10:00",
        "OccasionToDate": "2020-01-04 14:00",
        "FomKlo": "10:00",
        "TomKlo": "14:00",
        "TimeBefore": "0",
        "TimeAfter": "0",
        "Weekday": 0,
        "BookStatus": "",
        "KortReg": "",
        "CustomerID": "",
        "CustomerName": "* Odense Håndbold talentcenter",
        "TypeOfBooking": "E",
        "CreatedBy": "",
        "Cards": null,
        "FunctionCode1": 0,
        "FunctionCode2": 0,
        "FunctionCode3": 0,
        "FunctionCode4": "",
        "Text1": "",
        "Text2": "",
        "Text3": "",
        "Text4": "",
        "EndUser": "",
        "Activity": "Styrketræning"
      }
    ]
  },
  "ResultCode": 0,
  "ResultText": null
}

Мои классы данных определены следующим образом

data class Bookings(val AccessControlRecords: AccessControlRecords, val resultCode: Int, val resultText: String?)

data class AccessControlRecords(val OccasionRecords: List<OccasionRecords>)

data class OccasionRecords(val type: String?,
                           val BookingNr: String,
                           val bookingRow: String,
                           val FacilityID: String,
                           val ObjectID: String,
                           val PartOfObjectId: String,
                           val PartOfObjectName: String,
                           val FacilityName: String,
                           val ObjectName: String,
                           val BookFromDate: String,
                           val BookToDate: String,
                           val OccasionDate: String,
                           val OccasionToDate: String,
                           val FomKlo: String,
                           val TomKlo: String,
                           val TimeBefore: String,
                           val TimeAfter: String,
                           val Weekday: Int,
                           val BookStatus: String,
                           val KortReg: String,
                           val CustomerID: String,
                           val CustomerName: String,
                           val TypeOfBooking: String,
                           val CreatedBy: String,
                           val Cards: String,
                           val FunctionCode1: Int,
                           val FunctionCode2: Int,
                           val FunctionCode3: Int,
                           val FunctionCode4: String,
                           val Text1: String,
                           val Text2: String,
                           val Text3: String,
                           val Text4: String,
                           val EndUser: String,
                           val Activity: String)

Мой класс конфигурации определен следующим образом

class BookingConfiguration {
    companion object {
        const val URL = "https://something.dk"
        const val PATH = "/kmd_webapi/api/Monitor/GetFilteredAccessControlRecords?dateTimeFrom=2020-01-04&dateTimeTo=2020-01-04&facility=OIHAL&facilityObject=STYRK&partObject=&authenticationCode=xxx&type=json"
    }
}

Фактический клиент определяется следующим образом:

@Client(BookingConfiguration.URL)
interface BookingsClient {
    @Get(BookingConfiguration.PATH)
    fun fetchBookings(dateTimeFrom: String, dateTimeTo: String, authenticationCode: String): Flowable<Bookings>
}

Исключение, которое я получаю, следующее:

01:31:59.199 [pool-1-thread-3] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Error decoding JSON stream for type [T]: Instantiation of [simple type, class dk.fitfit.OccasionRecords] value failed for JSON property BookingNr due to missing (therefore NULL) value for creator parameter BookingNr which is a non-nullable type
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: dk.fitfit.Bookings["AccessControlRecords"]->java.lang.Object[0]->dk.fitfit.OccasionRecords["BookingNr"])
io.micronaut.http.codec.CodecException: Error decoding JSON stream for type [T]: Instantiation of [simple type, class dk.fitfit.OccasionRecords] value failed for JSON property BookingNr due to missing (therefore NULL) value for creator parameter BookingNr which is a non-nullable type
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: dk.fitfit.Bookings["AccessControlRecords"]->java.lang.Object[0]->dk.fitfit.OccasionRecords["BookingNr"])
    at io.micronaut.jackson.codec.JsonMediaTypeCodec.decode(JsonMediaTypeCodec.java:123)
    at io.micronaut.http.client.DefaultHttpClient.lambda$null$17(DefaultHttpClient.java:905)
    at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:63)
    at io.micronaut.reactive.rxjava2.InstrumentedSubscriber.lambda$onNext$0(InstrumentedSubscriber.java:80)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:52)
...

Я заметил, что свойство Bookings.AccessControlRecords имеетбыть заглавными. Но Bookings.resultCode и Bookings.resultText не делает то, что я нашел странным. То же самое с AccessControlRecords.OccasionRecords. Конечно, я экспериментировал с различными случаями для свойства BookingNr, но безрезультатно.

Кто-нибудь может сказать мне, что я делаю неправильно? Или, может быть, у кого-то есть подсказка о том, как отладить это дальше?

1 Ответ

0 голосов
/ 04 ноября 2019

Использование @JsonProperty, как показано ниже, решило проблему.

data class Bookings(@JsonProperty("AccessControlRecords") val accessControlRecords: AccessControlRecords, val resultCode: Int, val resultText: String?)
...