ObjectMapper для веб-клиента - PullRequest
0 голосов

У меня проблема:

Class: TalonInfo, field which deserization: private Instant registrationTime;
Class: ServiceTalonImpTest, methode: void getInfo(),= client.getinfo("136-187-933-84-0000", talonUUID).block(); 

// Когда я пытаюсь запустить эту строку кода, появляется ошибка:

JSON decoding error: Cannot deserialize value of type `java.time.Instant` from String "Feb 19, 2020 5:30:00 PM": 
Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text 'Feb 19, 2020 5:30:00 PM' could not be parsed at index 13; nested exception is com.fasterxml.jackson.databind.exc.
InvalidFormatException: Cannot deserialize value of type `java.time.Instant` from String "Feb 19, 2020 5:30:00 PM": 
Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) 
Text 'Feb 19, 2020 5:30:00 PM' could not be parsed at index 13

I необходимо настроить objectMapper; У WebClient есть собственный ObjectMapper.

К сожалению, я не понимаю, как настроить objectMapper для веб-клиента, и был бы признателен за любые рекомендации или примеры.

@SpringBootApplication
public class StartApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(ru.tularegion.mfc.StartApplication.class, args);
    }

    @Bean
    public ObjectMapper objectMapper() {
        var mapper = new ObjectMapper();

        JavaTimeModule module = new JavaTimeModule();
        mapper.registerModule(module);
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.findAndRegisterModules();
        return mapper;
    }
}


class TalonInfo {
....

    /**
     * Adress filial
     */
    @JsonProperty("affiliateAddress")
    private String affiliateAddress;

    /**
     * Pre-recorded date
     */
    @JsonProperty("regTime")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MMM dd, yyyy HH:mm:ss a", locale = "en")
    private Instant registrationTime;

    /**
     * Coupon Prefix
     */
    @JsonProperty("prefix")
    private String prefix;

}  


@RequiredArgsConstructor
public class ServiceTalonImp implements ServiceTalon {

@Override
    @Nonnull
    public Mono<TalonInfo> getinfo (String userId, List<Talon> talonUUID) {

        Timer.Sample sample = init(meterRegistry, "/infobox/ticket/getinfo");
        return webClient.post()
                .uri("/infobox/ticket/getinfo")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .onStatus(HttpStatus::isError, handleError(meterRegistry, sample, "/infobox/ticket/getinfo"))
                .bodyToMono(TalonInfo.class)
                .doOnSuccess(mapSuccessMono(meterRegistry, sample, "/infobox/ticket/getinfo"))
                .name("mfc.api.get_info");
    }
}




@SpringBootTest
public class ServiceTalonImpTest {
    private static MockWebServer server;
    private ServiceTalon client;


    @BeforeAll
    static void init() throws IOException, ParseException {
        BlockHound.install();
        Date date = new SimpleDateFormat("MMM dd, yyyy hh:mm:ss a", Locale.ENGLISH).parse("Feb 19, 2020 5:30:00 PM");
    }

    @AfterAll
    static void tearDown() throws IOException {
        server.shutdown();
    }

    @BeforeEach
    void setUp() throws IOException {
        //store = mock(RhisDataStore.class);
        if (server != null) {
            server.shutdown();
            server = new MockWebServer();
            server.start();
        } else {
            server = new MockWebServer();
            server.start();
        }
        var webClient = WebClient.builder()
                .baseUrl(server.url("/").toString())
                .build();

        client = new ServiceTalonImp(webClient, new SimpleMeterRegistry());
    }
    @Test
    void getInfo() throws InterruptedException, ParseException {
        var resourse = this.getClass().getClassLoader().getResourceAsStream("ru.tularegion.mfc.spring.clientImplementation.test/talonInfo.json");
        assert resourse !=null;
        var text = new Scanner(resourse, StandardCharsets.UTF_8).useDelimiter("\\A").next();
        server.enqueue(new MockResponse()
                .setResponseCode(200)
                .setHeader(HttpHeaders.CONTENT_TYPE, "application/json")
                .setHeader("Connection","close")
                .setBody(text));

        var talon = new Talon();

        talon.setId(UUID.fromString("c3e2b5e3-e66b-472b-a053-09e2ac63523d"));

        List<Talon> talonUUID = new ArrayList<Talon>();

        talonUUID.add(talon);

        var talonInfo  = client.getinfo("136-187-933-84-0000", talonUUID).block(); // When I am try run this line of code, I have errore = "JSON decoding error: Cannot deserialize value of type `java.time.Instant` from String "Feb 19, 2020 5:30:00 PM": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text 'Feb 19, 2020 5:30:00 PM' could not be parsed at index 13; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.Instant` from String "Feb 19, 2020 5:30:00 PM": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text 'Feb 19, 2020 5:30:00 PM' could not be parsed at index 13"


        assertNotNull(talonInfo);
        assertEquals(UUID.fromString("c3e2b5e3-e66b-472b-a053-09e2ac63523d"), talonInfo.getId());
        assertEquals(UUID.fromString("7bb9219d-8dec-4cbb-b458-a4e4e43e15b4"), talonInfo.getServiceId());
        assertEquals("Подача документов", talonInfo.getServiceName());
        assertEquals(UUID.fromString("8fc908e4-8664-4571-84ef-27eea35a9ba0"), talonInfo.getAffiliateId());
        assertEquals("Отделение №02: пгт. Арсеньево, ул. Бандикова, д 79", talonInfo.getAffiliateAddress());
        Instant registrationTime = new SimpleDateFormat ("MMM dd, yyyy hh:mm:ss a", Locale.UK).parse("Feb 19, 2020 5:30:00 PM").toInstant();
        assertEquals(registrationTime, talonInfo.getRegistrationTime());

        assertEquals("ru_a", talonInfo.getPrefix());
        assertEquals(1, talonInfo.getNum());
        assertEquals("Иевская Анастасия Сергеевна", talonInfo.getRequesterName());
        assertEquals(Talon.Status.WAIT, talonInfo.getStatus());
        assertEquals("7(953)9743532", talonInfo.getPhone());
        assertEquals("nastena.24.89@mail.ru", talonInfo.getEmail());
        assertEquals(0, talon.getCabNum());

        var request = server.takeRequest();
        assertEquals("/infobox/ticket/getinfo", Objects.requireNonNull(request.getRequestUrl()).encodedPath());
        assertEquals("POST", request.getMethod());
    }
}

This Json need deserilzation:


{ 
  "uuid": "c3e2b5e3-e66b-472b-a053-09e2ac63523d", 
  "serviceUuid": "7bb9219d-8dec-4cbb-b458-a4e4e43e15b4", 
  "serviceName": "Подача документов", 
  "affiliateUuid": "8fc908e4-8664-4571-84ef-27eea35a9ba0", 
  "affiliateAddress": "Отделение №02: пгт. Арсеньево, ул. Бандикова, д 79", 
  "regTime": "Feb 19, 2020 5:30:00 PM", 
  "prefix": "ru_a", 
  "number": 1, 
  "requesterName": "Иевская Анастасия Сергеевна", 
  "status": "WAIT", 
  "fields": { 
  }, 
  "phone": " 7(953)9743532", 
  "email": "nastena.24.89@mail.ru", 
  "cabNum": 0 
}

Ответы [ 2 ]

0 голосов
/ 19 июня 2020

У вас неправильный формат даты. «ЧЧ» - имеет интервал 00–23, если вы используете 17:30 - «ЧЧ: мм» недопустимый формат времени. Вместо этого следует использовать «ч: мм». Подробнее - https://docs.oracle.com/javase/9/docs/api/java/text/SimpleDateFormat.html

0 голосов
/ 19 июня 2020

Вы можете зарегистрировать свой ObjectMapper, чтобы использовать его в качестве кода сообщения c в webflux.

    @Bean
    Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper mapper){
       return new Jackson2JsonEncoder(mapper);
    }

    @Bean
    Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper mapper){
        return new Jackson2JsonDecoder(mapper);
    }

    @Bean
    WebFluxConfigurer webFluxConfigurer(Jackson2JsonEncoder encoder, Jackson2JsonDecoder decoder){
        return new WebFluxConfigurer() {
            @Override
            public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
                configurer.defaultCodecs().jackson2Encoder(encoder);
                configurer.defaultCodecs().jackson2Decoder(decoder);
            }
        };

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