DTO中的动态字段类型

You*_*sef 3 java spring spring-mvc jackson

我正在使用,Spring-MVC并且具有如下所示的DTO结构,JSON用于从客户端(foo实体)接收数据,并使用以下命令将其保存到数据库中JPA

public class FooDTO {

    public Integer id;
    public String label;
    public Double amount;
    public List<Integer> states;
    ...
Run Code Online (Sandbox Code Playgroud)

但是当客户想要编辑foo实体时,我必须像下面这样构造它

public class FooDTO {

    public Integer id;
    public String label;
    public Double amount;
    public List<SimpleDto> states;
    ...
Run Code Online (Sandbox Code Playgroud)

SimpleDto

public class SimpleDto {
    public Integer value;
    public String label;
}
Run Code Online (Sandbox Code Playgroud)

区别只是states有时List<SimpleDto>和有时是类型,List<Integer>而我不想创建另一个dto。

那么如何在dto(json)中实现动态字段类型呢?

P.S JSON data is handled by com.fasterxml.jackson.core

Man*_*nan 6

使用自定义解串器是解决问题的一种方法

    public class DynamicDeserializer extends JsonDeserializer {
    @Override
    public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String requestString = jp.readValueAsTree().toString();
        JSONArray jo = new JSONArray(requestString);
        List<SimpleDto> simpleDtoList = new ArrayList<>();
        List<Integer> integers = new ArrayList<>();
        if(jo!=null && jo.length()>0) {
            for (int i = 0; i < jo.length(); i++) {
                Object string = jo.get(0);
                if(string!=null && string instanceof JSONObject){
                    JSONObject value = jo.getJSONObject(i);
                    SimpleDto simpleDto = new SimpleDto();
                    simpleDto.setValue(value.getInt("value"));
                    simpleDtoList.add(simpleDto);
                }else{
                    integers.add(jo.getInt(0));
                }
            }
        }


        return integers.isEmpty() ? simpleDtoList:integers;
    }
}
Run Code Online (Sandbox Code Playgroud)

发送请求并打印回的控制器

@PostMapping("/test")
    public Optional<TestObject> testDynamicMapper(
            @RequestBody final TestObject testObject) {
        List<Object> states = testObject.getStates();

        for (Object object:states) {
            if(object instanceof SimpleDto){
                SimpleDto dto = (SimpleDto)object;
                System.out.println(dto.getValue());
            }
            if(object instanceof Integer){
                Integer dto = (Integer)object;
                System.out.println(dto);
            }
        }


        return Optional.of(testObject);
    }
Run Code Online (Sandbox Code Playgroud)

有通用映射的pojo类

public class TestObject implements Serializable {

    @JsonDeserialize(using = DynamicDeserializer.class)
    private List<Object> states;


    public List<Object> getStates() {
        return states;
    }

    public void setStates(List<Object> states) {
        this.states = states;
    }


}
Run Code Online (Sandbox Code Playgroud)

输入对象列表的有效负载

{
  "states": [
    {
      "label": "1",
      "value": 0
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

输入有效内容以获取整数列表

{
  "states": [
      1,2
  ]
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*all 0

使用适合您的 DTO 类型的 Spring 类型转换器。这样,客户端可以发布 stateId,转换器将为给定 ID 解析正确的 DTO 类型。

这是一个例子: https: //www.baeldung.com/spring-type-conversions