Как я могу использовать такой JSON с помощью RestTemplate? - PullRequest
0 голосов
/ 10 июля 2019

Я пытаюсь использовать json, который содержит карту, но ничего не работает. Все, что я получаю, является нулем.

Я пытался использовать методы getForObject (), getForEntity () с типом ответа типизации типа оболочки ConsulServicesResponse.class, но ничего не работает. Использование Object вместо ConsulServicesResponse работает нормально, но я бы предпочел использовать строгую типизацию.

У меня есть такой json, исходящий от моего консула агента api:

{
    "synchronizer-1-0": {
        "ID": "synchronizer-1-0",
        "Service": "synchronizer-1-0",
        "Tags": [
            "synchronize"
        ],
        "Meta": {},
        "Port": 8080,
        "Address": "localhost",
        "Weights": {
            "Passing": 1,
            "Warning": 1
        },
        "EnableTagOverride": false
    }
}

как видите, "synchronizer-1-0": {...} это карта. Я создал модель, которую следует использовать при потреблении: Это оболочка ответа:

@Getter
@Setter
public class ConsulServicesResponse {

    @JsonProperty
    private String name;

    @JsonProperty
    private ConsulService services;

}

Это значение POJO:

@NoArgsConstructor
@Getter
@JsonIgnoreProperties(ignoreUnknown = true)
public class ConsulService implements Serializable {

    @JsonProperty(value = "ID")
    private String id;

    @JsonProperty(value = "Service")
    private String service;

    @JsonProperty(value = "Tags")
    private String[] tags;

    @JsonProperty(value = "Meta")
    private String meta;

    @JsonProperty(value = "Port")
    private Integer port;

    @JsonProperty(value = "Address")
    private String address;

    @JsonProperty(value = "Weights")
    private Weights weights;

    @JsonProperty(value = "EnableTagOverride")
    private Boolean enableTagOverride;

    private class Weights {

        @JsonProperty(value = "Passing")
        private Integer passing;

        @JsonProperty(value = "Warning")
        private Integer warning;

    }
}

Для правильной сериализации / десериализации я добавляю отображения по умолчанию в мой компонент RestTemplate следующим образом:

@Configuration
public class AppConfiguration {

    @Bean
    RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
        return restTemplate;
    }

    @Bean
    @Scope("singleton")
    ConsulCache consulCache(){
        return new ConsulCache();
    }

}

И, наконец, в моем контроллере я использую сервис, где я вызываю restTemplate:

@Component
public class ConsulCacheUpdater {

    private static final Logger log = LoggerFactory.getLogger(ConsulCacheUpdater.class);

    private final String AGENT_PREFIX = "v1/agent/";
    private final String CONSUL_SERVICES = "services";
    private final String PRETTY_VIEW = "?pretty";

    @Autowired
    ApplicationContext ctx;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    Environment environment;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ConsulCache consulCache;

    @Scheduled(initialDelay = 3_000, fixedRate = 30_000)
    public void updateServiceList(){

        String consul_url = String.format("http://%s:%s/%s%s",
                environment.getProperty("spring.cloud.consul.host"),
                environment.getProperty("spring.cloud.consul.port"),
                AGENT_PREFIX,
                CONSUL_SERVICES + PRETTY_VIEW);

        ResponseEntity<ConsulServicesResponse> response = restTemplate.exchange(
                consul_url,
                HttpMethod.GET,
                null,
                ConsulServicesResponse.class);

        if (response.getStatusCode().equals(HttpStatus.OK)){

            ConsulServicesResponse cs = response.getBody();

        }
    }
}

Итак, мой CS нулевой. Что я делаю не так?

...