jackson Sping Boot 使用Json作为请求参数,而不是实体/模型

7vhp5slm  于 2022-11-08  发布在  其他
关注(0)|答案(5)|浏览(134)

我们公司正计划将我们的微服务技术转换为Sping Boot 。作为一项计划,我做了一些高级阅读,并记下了它的潜在影响和语法等价物。我还开始移植我们现有的最小服务作为一个附带项目。
一个阻碍我进步的问题是试图将Json请求/响应交换转换为 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
}

在Sping 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) {}

我的问题是MyModel 1可能不一定包含我的json数据所具有的字段/参数。
Nutz非常有用的一点是,如果我删除了JsonAdapter,它的行为就像Spring中的常规表单请求端点。
我在Stack中找不到答案,或者如果可能的话,我对它的称呼与现有的Spring开发人员对它的称呼不同。
我们的老板期望我们(不切实际地)在不强迫前端开发人员适应这些变化的情况下实现这些变化。(自治等等)如果这是不可避免的,那么对此有什么合理的解释呢?

ukdjmx9f

ukdjmx9f1#

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

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

1cosmwyk2#

其实我想到了一个更直接的解决办法。
显然这是可行的:

@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请求对象那样Map,则此操作有效。例如:

public class MyWebRequestObject {
   String value_1;
   String value_2
}

未Map的值会被忽略。Spring就是这样聪明。
我知道这就回到了我开始的地方,但是由于我们引入了一个服务层供rest控件与之交互,因此创建我们自己的请求模型对象(DTO)是有意义的,该对象与持久性模型是分开的。

kqlmhetl

kqlmhetl3#

可以将@RequestBodyMap用作@PostMapping,@PutMapping和@PatchMapping的参数。对于@GetMapping和@DeleteMapping,可以编写一个实现Converter的类,以便将JSON格式的请求参数转换为Map。然后,可以将该类注册为带有@Component注解的Bean。然后,可以将参数绑定到@RequestParameterMap。
下面是一个转换器示例。

@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<>();
        }
    }

}

如果要排除MyModel 1类的特定字段,请对该字段使用@JsonIgnore注解,如下所示。

class MyModel1 {
     private field1;
     @JsonIgnore field2;
}

那么,我想你可以用你所做的。(我不确定。)

public Object (@RequestBody MyModel1 model1) {}
os8fio9y

os8fio9y4#

我认为您可以使用涉及dto https://auth0.com/blog/automatically-mapping-dto-to-entity-on-spring-boot-apis/策略,
在您可以像实体一样Map或根据需要使用它之后,您可以将json发送到像dto对象一样MapRestapi

3ks5zfa0

3ks5zfa05#

请尝试以下操作:
添加新的注解JsonParam并实现this的HandlerMethodArgumentResolver,解析json以Map并获取HandlerMethodArgumentResolver中的数据
第一个问题

相关问题