java - DTO 中的动态字段类型

标签 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;
    ...

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

public class FooDTO {

    public Integer id;
    public String label;
    public Double amount;
    public List<SimpleDto> states;
    ...

SimpleDto

public class SimpleDto {
    public Integer value;
    public String label;
}

区别只是 states有时输入 List<SimpleDto>有时 List<Integer>而且我不想创建另一个 dto。

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

P.S JSON数据由com.fasterxml.jackson.core处理

最佳答案

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

    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;
    }
}

发送和打印请求的 Controller

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

有泛型映射的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;
    }


}

对象列表的输入负载

{
  "states": [
    {
      "label": "1",
      "value": 0
    }
  ]
}

整数列表的输入负载

{
  "states": [
      1,2
  ]
}

关于java - DTO 中的动态字段类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55912805/

相关文章:

java - 如何使用 Spring ClassPathResource : with classpath: or classpath*: and leading/or not?

java - Spring Security BCryptPasswordEncoder 已插入但不匹配

jQuery 选项卡 : Post previously selected tab when opening a new one

java - 是否可以为@PathVariable 的值定义一个范围?

java - JOOQ MockDataProvider - 如何根据某些条件返回不同的模拟?

java - Java进程的dump文件分析?

java - java FileInputStream 和 FileOutputStream 出错

java - 使用带有 Double[] 作为参数的 java 反射时出现 noSuchMethodException

java - 无法打开 Spring 类路径资源 [applicationContext.xml],因为它不存在

java - 具有运行时确定的构造函数参数的部分 Autowiring Spring 原型(prototype) bean