使用Json作为请求参数而不是实体/模型的Spring Boot

时间:2018-03-30 12:02:59

标签: java json spring spring-boot jackson

我们公司计划将微服务技术转换为Spring Boot。作为一项计划,我做了一些高级阅读,并注意到它的潜在影响和语法等价物。我也开始移植我们作为辅助项目的最小服务。

阻止我进度的一个问题是尝试将我们的Json请求/响应交换转换为Spring Boot。

以下是代码示例:(对于那些不认识这一点的人来说,这是Nutz框架)

@POST
@At // These two lines are equivalent to @PostMapping("/create")
@AdaptBy(type=JsonAdapter.class)
public Object create(@Param("param_1") String param1, @Param("param_2) int param2) {
    MyModel1 myModel1 = new MyModel1(param1);
    MyModel2 myModel2 = new MyModel2(param2);
    myRepository1.create(myMode12);
    myRepository2.create(myModel2);
    return new MyJsonResponse();
}

在PostMan或任何其他REST客户端上,我只是传递POST:

{
    "param_1" : "test",
    "param_2" : 1
}

我在Spring Boot中做到了这一点:

@PostMapping("/create")
public Object create(@RequestParam("param_1") String param1, @RequestParam("param_2) int param2) {
    MyModel1 myModel1 = new MyModel1(param1);
    MyModel2 myModel2 = new MyModel2(param2);
    myRepository1.create(myMode12);
    myRepository2.create(myModel2);
    return new MyJsonResponse();
} 

我不知道如何在这里做类似JsonAdapter的事情。 Spring并不认识我传递的数据。

我尝试了这个但基于这些例子,它希望Json参数是实体的形式。

@RequestMapping(path="/wallet", consumes="application/json", produces="application/json")

但是如果我这样做的话,我只能做到这一点:

public Object (@RequestBody MyModel1 model1) {}

我的问题是MyModel1可能不一定包含我的json数据所具有的字段/参数。

关于Nutz非常有用的一点是,如果我删除了JsonAdapter,它在春天的行为就像一个常规的表单请求端点。

我无法在Stack中找到答案,或者如果可能的话,我调用它的方式与现有的Spring开发人员所称的不同。

我们的老板希望我们(不切实际地)实施这些变更,而不必强迫前端开发人员适应这些变化。 (自治和所有爵士乐)。如果这是不可避免的,对此会有什么明智的解释?

4 个答案:

答案 0 :(得分:3)

在这种情况下,您可以使用Map类来读取输入json,例如

@PostMapping("/create")
public Object create(@RequestBody Map<String, ?> input) {
     sout(input.get("param1")) // cast to String, int, ..
}

答案 1 :(得分:2)

我实际上找到了一个更直接的解决方案。

显然这有效:

@PostMapping("/endpoint")
public Object endpoint(@RequestBody MyWebRequestObject request) {
    String value1 = request.getValue_1();
    String value2 = request.getValue_2();
}

json有效载荷是这样的:

{
   "value_1" : "hello",
   "value_2" : "world"
}

如果MyRequestObject像json请求对象一样被映射,则这是有效的。例如:

public class MyWebRequestObject {
   String value_1;
   String value_2
}

忽略未映射的值。春天很聪明。

我知道这是我刚开始的地方,但是由于我们为其余控件引入了一个服务层来进行交互,因此创建我们自己的请求模型对象(DTO)与持久性模型是分开的。

答案 2 :(得分:0)

您可以使用@RequestBody Map作为@PostMapping,@ PutMapping和@PatchMapping的参数。对于@GetMapping和@DeleteMapping,您可以编写一个实现Converter的类,以便将json形成的请求参数转换为Map。并且您将该类注册为具有@Component注释的bean。然后,您可以将参数绑定到@RequestParameter Map。

以下是转换器的示例。

@Component
public class StringToMapConverter implements Converter<String, Map<String, Object>> {

    private final ObjectMapper objectMapper;

    @Autowired
    public StringToMapConverter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Map<String, Object> convert(String source) {
        try {
            return objectMapper.readValue(source, new TypeReference<Map<String, Object>>(){});
        } catch (IOException e) {
            return new HashMap<>();
        }
    }

}

如果要排除MyModel1类的特定字段,请在字段中使用@JsonIgnore注释,如下所示。

class MyModel1 {
     private field1;
     @JsonIgnore field2;
}

然后,我猜你可以使用你所做的事情。(我不确定。)

public Object (@RequestBody MyModel1 model1) {}

答案 3 :(得分:0)

我认为您可以使用涉及dto的策略 https://auth0.com/blog/automatically-mapping-dto-to-entity-on-spring-boot-apis/

您可以将json发送到您的rest api,这是一个dto对象的地图,之后您可以像实体一样映射或根据您的需要使用它