簡體   English   中英

使 Spring 使用 Jackson 在 GET 端點中轉換 JSON 編碼的@RequestParam

[英]Make Spring use Jackson to convert JSON encoded @RequestParam in GET endpoint

這是我在stackoverflow中的第一個問題,所以請溫柔:)

有一個現有的 GET 端點可以轉換為 POST。 它需要擴展以接受查詢參數filterKeys ,該參數將包含 JSON 編碼數據。 這種方法不是很常見,但是一些大型 API 正在使用它。 The working approach is to map the query parameter to a String and then deserialised to a Java object by using the Jackson ObjectMapper within the controller method. 有什么方法可以在后台某處應用此 Jackson 反序列化,就像 Spring 開箱即用地支持@RequestBody一樣?

JSON 編碼filterKeys的示例:

[
  {
    "parameter": "datetime",
    "value": {
      "type": "INT_RANGE",
      "start": 1275782400,
      "end": 1571443199
    }
  },
  {
    "parameter": "value",
    "value": {
      "type": "LONG_RANGE",
      "start": 100,
      "end": 200
    }
  }
]

Java object:

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;

import javax.validation.constraints.NotNull;
import java.util.List;

@Getter
@AllArgsConstructor
@JsonInclude
public class FilterKeyRequest {

    @NotNull
    private String parameter;
    @NotNull
    private FilterValue value;

}

我嘗試簡單地將filterKeys FilterKeyRequest當然不起作用。 當前的解決方案是在 controller 方法中進行反序列化:

@GetMapping("/data")
public List<TransferResponse> getData(@RequestParam(required = false) int someOtherParam,
                                          @RequestParam(required = false) String filterKeys) throws BadFilterKeyParameter {

        List<FilterKeyRequest> filters = List.of();
        try {
            filters = objectMapper.readValue(filterKeys, new TypeReference<List<FilterKeyRequest>>() {});
        } catch (IOException e) {
            throw new BadFilterKeyParameter("The filterKeys parameters couldn't be encoded due do bad JSON format");
        }

        return someService.getData(someOtherParam, filters);
    }

我真的很想在后台的某個地方優雅地處理這個問題。 org.springframework.core.convert.converter.Converterorg.springframework.web.method.support.HandlerMethodArgumentResolver可能會以某種方式實現。 最好不要顯式調用 Jackson object 映射器。

更新:我找到了一個帶有Converter的解決方案,但這仍然意味着明確調用 Jackson ObjectMapper ,但我可以接受:

@Slf4j
@RequiredArgsConstructor
@Component
public class FilterKeyConverter implements Converter<String, List<FilterKeyRequest>> {

    private final ObjectMapper mapper;

    @Override
    public List<FilterKeyRequest> convert(String source) {
        List<FilterKeyRequest> filters = List.of();
        try {
            filters = mapper.readValue(source, new TypeReference<List<FilterKeyRequest>>() {});
        } catch (IOException e) {
            log.warn("The parameter couldn't be encoded due do bad JSON encoding");
        }
        return filters;
    }
}

您的 getData() 方法應在 @RestController 注釋的 class (而不是@Controller)中定義

@RestController
public DataController {
    @GetMapping("/data")
    public List<TransferResponse> getData(@RequestParam(required = false) int someOtherParam,
                                          @RequestParam(required = false) String filterKeys) throws BadFilterKeyParameter {

        List<FilterKeyRequest> filters = List.of();
        try {
            filters = objectMapper.readValue(filterKeys, new TypeReference<List<FilterKeyRequest>>() {});
        } catch (IOException e) {
            throw new BadFilterKeyParameter("The filterKeys parameters couldn't be encoded due do bad JSON format");
        }

        return someService.getData(someOtherParam, filters);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM