为了账号安全,请及时绑定邮箱和手机立即绑定

DTO 中的动态字段类型

DTO 中的动态字段类型

POPMUISE 2022-10-26 17:24:43
我正在使用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;    ...和SimpleDtopublic class SimpleDto {    public Integer value;    public String label;}区别只是states它有时List<SimpleDto>有时的类型List<Integer>而且我不想创建另一个 dto。那么如何在我的 dto (json) 中实现动态字段类型呢?PS JSON 数据由com.fasterxml.jackson.core
查看完整描述

4 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

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


    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;

    }

}

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


@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

  ]

}


查看完整回答
反对 回复 2022-10-26
?
慕的地8271018

TA贡献1796条经验 获得超4个赞

我建议你使用不同的类:FooInfoDTO、FooDetailsDTO。它通常在您有主从表单时使用。在 master(table) 中,您显示有关对象的简短信息(一个 DTO),然后导航到您获取完整对象数据(另一个 DTO)的详细信息



查看完整回答
反对 回复 2022-10-26
?
繁星coding

TA贡献1797条经验 获得超4个赞

写一个dto


public class FooDTO {


    public Integer id;

    public String label;

    public Double amount;

    public List<Object> states;

}

在 Service 类中对 DTO 进行类型转换并处理异常


查看完整回答
反对 回复 2022-10-26
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

您可以尝试完全重新设计架构。使用相关集合拆分主实体。


提供独立服务来为您的实体添加/删除/设置状态。通过这种方式,您可以轻松地为您的客户端提供 REST 服务,使用起来一目了然。


这是一组可能的方法,通过 REST 接口实现:


@Path(../foo)

@Produces

public interface FooService {

  //CRUD methods on Foo itself which work with attributes of Foo only

  ...

  @GET

  @Path("/{fooId}")

  FooDTO findById(@PathParam("fooId") int fooId);


  //status-related methods:

  @GET

  @Path("/{fooId}/status")

  List<SimpleDto> statuses(@PathParam("fooId") int fooId);


  @Post

  @Path("/{fooId}/status")

  void addStatus(@PathParam("fooId") int fooId, int statusId);


  @DELETE

  @Path("{fooId}/status")

  void deleteStatus(@PathParam("fooId") int fooId, int statusId);


  @PUT

  @Path("/status")

  void setStatuses(@PathParam("fooId") int fooId, List<Integer> newStatuses);

}

有了这个解决方案,还有一些替代选项,我更愿意返回:


  @GET

  @Path("/{fooId}/status")

  List<Integer> statuses(@PathParam("fooId") int fooId);

而不是 DTO 列表。然后将提供一项服务来获取所有状态及其名称,而无需连接到 Foo:


public interface StatusService {

  List<SimpleDto> statuses();

}

为了简化 GUI 组件的实现,您可以创建将返回组合数据的 Rest 服务,就像在您的第二个 FooDto 版本中一样。它还将减少休息电话的数量。但是拥有单独的方法来直接处理项目集合会很有帮助。


查看完整回答
反对 回复 2022-10-26
  • 4 回答
  • 0 关注
  • 142 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号