休息模板 |读取未知的 ENUM 值作为默认值
RestTemplate | Reading unknown ENUM values as default value
我正在使用 org.springframework:spring-web:5.1.9.RELEASE
并且有一个普通的(未定制的)RestTemplate
class 对象,我用它来发送 POST 使用 EXCHANGE 方法请求。我想让它反序列化来自 response 的未知 ENUM 值到它们的默认值(使用 @JsonEnumDefaultValue
设置)而不是失败整个操作。我已经搜索过,但没有找到任何简单的方法来做到这一点,你能给我一些帮助吗?谢谢!
@Service
@CommonsLog
public class TMServerExternalApiRepositoryImpl implements TMServerExternalApiRepository {
private final RestTemplate restRelay;
private TeleMessageProperties tmUrls;
@Autowired
public TMServerExternalApiRepositoryImpl(RestTemplate restTemplate, TeleMessageProperties tmProperties) {
this.restRelay = restTemplate;
this.tmUrls = tmProperties;
}
@Override
public VnvUsersSearchResult getUsersByPhone(String to, String from) {
log.info(String.format("Trying to get users with telephones to: [%s], from: [%s] ", to, from));
return sendRequest(new VnvUserSearchParams(from, to), VnvUsersSearchResult.class, tmUrls.getGetUserByPhoneUrl()).getBody();
}
//the actual post
private <T, K> ResponseEntity<T> sendRequest(K content, Class<T> returnTypeClass, String url) throws HttpClientErrorException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<K> httpEntity = new HttpEntity<>(content, httpHeaders);
return restRelay.exchange(url, HttpMethod.POST, httpEntity, returnTypeClass);
}
}
这是我现在遇到的异常:
org.springframework.web.client.RestClientException: Error while extracting response for type [class voiceAndVideo.services.VnvUsersSearchResult] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `voiceAndVideo.Util.VNVDevice$Type` from String "BAD_VALUE": value not one of declared Enum instance names: [MOBILE, ...]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `voiceAndVideo.Util.VNVDevice$Type` from String "BAD_VALUE": value not one of declared Enum instance names: [MOBILE, ...]
at [Source: (ByteArrayInputStream); line: 1, column: 261] (through reference chain: voiceAndVideo.services.VnvUsersSearchResult["userFrom"]->voiceAndVideo.Util.VNVUser["devices"]->java.util.ArrayList[2]->voiceAndVideo.Util.VNVDevice["type"])
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:117) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
类:
public class VnvUsersSearchResult {
private VNVUser userFrom;
...
}
public class VNVUser {
...
protected List<VNVDevice> devices;
...
}
public class VNVDevice {
public Type type;
String mobile;
public enum Type {
@JsonEnumDefaultValue
UNKNOWN(0),
MOBILE(10),
BUSINESS_PHONE(20),
...
int ID;
Type(int i) {
this.ID = i;
}
}
}
您可能需要为您正在使用的 RestTemplate
配置自定义 ObjectMapper
。您需要在 ObjectMapper
上启用 this feature。 请确保您使用的是 fasterxml 作为所有这些的包。
为了配置一个,像这样创建一个 JavaConfig 文件:
@Bean
public RestOperations restOperations() {
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
return rest;
}
@Bean
public MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
converter.setObjectMapper(myObjectMapper());
return converter;
}
@Bean
public ObjectMapper myObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
// This where you enable default enum feature
objectMapper.configure(DeserializationFeature. READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true);
return objectMapper;
}
我能够使用放置在 ENUM class 中的 JsonCreator 解决它。
@JsonCreator
public static Type getByValue(String t) {
return Arrays.stream(Type.values())
.filter(a -> a.name().equals(t)).findFirst().orElse(Type.UNKNOWN);
}
}
我正在使用 org.springframework:spring-web:5.1.9.RELEASE
并且有一个普通的(未定制的)RestTemplate
class 对象,我用它来发送 POST 使用 EXCHANGE 方法请求。我想让它反序列化来自 response 的未知 ENUM 值到它们的默认值(使用 @JsonEnumDefaultValue
设置)而不是失败整个操作。我已经搜索过,但没有找到任何简单的方法来做到这一点,你能给我一些帮助吗?谢谢!
@Service
@CommonsLog
public class TMServerExternalApiRepositoryImpl implements TMServerExternalApiRepository {
private final RestTemplate restRelay;
private TeleMessageProperties tmUrls;
@Autowired
public TMServerExternalApiRepositoryImpl(RestTemplate restTemplate, TeleMessageProperties tmProperties) {
this.restRelay = restTemplate;
this.tmUrls = tmProperties;
}
@Override
public VnvUsersSearchResult getUsersByPhone(String to, String from) {
log.info(String.format("Trying to get users with telephones to: [%s], from: [%s] ", to, from));
return sendRequest(new VnvUserSearchParams(from, to), VnvUsersSearchResult.class, tmUrls.getGetUserByPhoneUrl()).getBody();
}
//the actual post
private <T, K> ResponseEntity<T> sendRequest(K content, Class<T> returnTypeClass, String url) throws HttpClientErrorException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<K> httpEntity = new HttpEntity<>(content, httpHeaders);
return restRelay.exchange(url, HttpMethod.POST, httpEntity, returnTypeClass);
}
}
这是我现在遇到的异常:
org.springframework.web.client.RestClientException: Error while extracting response for type [class voiceAndVideo.services.VnvUsersSearchResult] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `voiceAndVideo.Util.VNVDevice$Type` from String "BAD_VALUE": value not one of declared Enum instance names: [MOBILE, ...]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `voiceAndVideo.Util.VNVDevice$Type` from String "BAD_VALUE": value not one of declared Enum instance names: [MOBILE, ...]
at [Source: (ByteArrayInputStream); line: 1, column: 261] (through reference chain: voiceAndVideo.services.VnvUsersSearchResult["userFrom"]->voiceAndVideo.Util.VNVUser["devices"]->java.util.ArrayList[2]->voiceAndVideo.Util.VNVDevice["type"])
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:117) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
类:
public class VnvUsersSearchResult {
private VNVUser userFrom;
...
}
public class VNVUser {
...
protected List<VNVDevice> devices;
...
}
public class VNVDevice {
public Type type;
String mobile;
public enum Type {
@JsonEnumDefaultValue
UNKNOWN(0),
MOBILE(10),
BUSINESS_PHONE(20),
...
int ID;
Type(int i) {
this.ID = i;
}
}
}
您可能需要为您正在使用的 RestTemplate
配置自定义 ObjectMapper
。您需要在 ObjectMapper
上启用 this feature。 请确保您使用的是 fasterxml 作为所有这些的包。
为了配置一个,像这样创建一个 JavaConfig 文件:
@Bean
public RestOperations restOperations() {
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
return rest;
}
@Bean
public MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
converter.setObjectMapper(myObjectMapper());
return converter;
}
@Bean
public ObjectMapper myObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
// This where you enable default enum feature
objectMapper.configure(DeserializationFeature. READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true);
return objectMapper;
}
我能够使用放置在 ENUM class 中的 JsonCreator 解决它。
@JsonCreator
public static Type getByValue(String t) {
return Arrays.stream(Type.values())
.filter(a -> a.name().equals(t)).findFirst().orElse(Type.UNKNOWN);
}
}