在將回應轉換為 DTO 之前,我可以看到它如下所示:
{
"name": "HalloweenBundle2021",
"pricing":
{
"VirtualCurrencyDto(physicalCurrency=EUR, coinId=null)":
{
"amount": 8.99,
"discountAmount": 0
},
"VirtualCurrencyDto(physicalCurrency=USD, coinId=null)":
{
"amount": 9.99,
"discountAmount": 0
}
}
}
哪個是正確的。
但是,在回應/實際轉換之后,這兩個physicalCurrency欄位都為空,而這些coinId欄位獲得完整的地圖值:
{
"name": "HalloweenBundle2021",
"pricing":
{
"VirtualCurrencyDto(physicalCurrency=null, coinId=VirtualCurrencyDto(physicalCurrency=EUR, coinId=null))":
{
"amount": 8.99,
"discountAmount": 0
},
"VirtualCurrencyDto(physicalCurrency=null, coinId=VirtualCurrencyDto(physicalCurrency=USD, coinId=null))":
{
"amount": 9.99,
"discountAmount": 0
}
}
}
究竟發生了什么?
我的回復 Pojo 是:
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class FooDto implements Serializable {
private String name;
private Map<VirtualCurrencyDto, PriceDto> pricing = new LinkedHashMap<>();
}
問題所在的 pojo 是:
@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class VirtualCurrencyDto implements Serializable {
// both of these fields should not be present, only one or the other
private DTOCurrency physicalCurrency; // an external enum
private String coinId;
public VirtualCurrencyDto(DTOCurrency physicalCurrency) {
this.physicalCurrency = physicalCurrency;
}
public VirtualCurrencyDto(String coinId) {
this.coinId = coinId;
}
}
我的 objectMapper bean
@Bean
public ObjectMapper getObjectMapper() {
return new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.ALWAYS)
.registerModule(new JsonNullableModule());
}
并且正在通過獲取回應 MockMvc
public FooDto getFooDto(String name) throws Exception {
MvcResult result =
mockMvc.perform(
get("/foo/" name))
.andExpect(status().isOk())
.andReturn();
return objectMapper.readValue(
result.getResponse().getContentAsString(), // this part is fine, when I look at the string value
FooDto.class); // issue here, upon conversion
}
我應該注意,在發出請求時也是如此,例如在請求到達我的控制器之前PUT,資料看起來不錯,但是在控制器中接收到它時,資料就像上面一樣(來自 的回應GET)。
uj5u.com熱心網友回復:
我的猜測是這個問題存在是因為你有一個復雜的物件作為你的pricingMap的鍵。JSON 中的映射由一個簡單的String鍵表示,值可以是一個復雜的物件。這意味著 Jackson 必須找到一種方法將您的復雜VirtualCurrencyDto物件序列化為一個簡單的String. 做到這一點的唯一方法是通過toString()方法,這就是為什么您會看到"VirtualCurrencyDto(physicalCurrency=null, coinId=VirtualCurrencyDto(physicalCurrency=EUR, coinId=null))". 這本身是錯誤的,因為您應該使用具有簡單String表示的簡單物件作為 JSON 映射中的鍵。但接下來,我們將了解為什么您會出現如此奇怪的行為。
Jackson 嘗試反序列"VirtualCurrencyDto(physicalCurrency=null, coinId=VirtualCurrencyDto(physicalCurrency=EUR, coinId=null))"化為一個VirtualCurrencyDto物件。由于它只包含一個String屬性,我的猜測是它創建了一個VirtualCurrencyDtowith實體"VirtualCurrencyDto(physicalCurrency=null, coinId=VirtualCurrencyDto(physicalCurrency=EUR, coinId=null))"作為 的值coinId, 中唯一的String屬性VirtualCurrencyDto,因此您正在經歷的行為。
您在這里有兩個選擇:
- 您查看模型類,以便使用一個簡單的物件作為
pricingMap的鍵。DTOCurrency例如,將是一個很好的候選人。 - 您創建一個自定義反序列化器,
VirtualCurrencyDto以便能夠決議String"VirtualCurrencyDto(physicalCurrency=null, coinId=VirtualCurrencyDto(physicalCurrency=EUR, coinId=null))"并創建類的實體。為此,您需要擴展StdDeserializer,然后在您的ObjectMapper. 類似于以下內容:
SimpleModule module = new SimpleModule()
.addDeserializer(VirtualCurrencyDto.class, new VirtualCurrencyDtoDeserializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
我會和第一個一起去。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/342760.html
上一篇:聲納錯誤:使用try-with-resources或在“finally”子句中關閉此“ZipOutputStream”
