猿问

DTO 中的动态字段类型

我正在使用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) 中实现动态字段类型呢?


PS JSON 数据由com.fasterxml.jackson.core


POPMUISE
浏览 143回答 4
4回答

九州编程

使用自定义解串器是解决问题的一种方法&nbsp; &nbsp; public class DynamicDeserializer extends JsonDeserializer {&nbsp; &nbsp; @Override&nbsp; &nbsp; public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {&nbsp; &nbsp; &nbsp; &nbsp; String requestString = jp.readValueAsTree().toString();&nbsp; &nbsp; &nbsp; &nbsp; JSONArray jo = new JSONArray(requestString);&nbsp; &nbsp; &nbsp; &nbsp; List<SimpleDto> simpleDtoList = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; List<Integer> integers = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; if(jo!=null && jo.length()>0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < jo.length(); i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object string = jo.get(0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(string!=null && string instanceof JSONObject){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSONObject value = jo.getJSONObject(i);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SimpleDto simpleDto = new SimpleDto();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; simpleDto.setValue(value.getInt("value"));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; simpleDtoList.add(simpleDto);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }else{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; integers.add(jo.getInt(0));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return integers.isEmpty() ? simpleDtoList:integers;&nbsp; &nbsp; }}发送请求并打印回来的控制器@PostMapping("/test")&nbsp; &nbsp; public Optional<TestObject> testDynamicMapper(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @RequestBody final TestObject testObject) {&nbsp; &nbsp; &nbsp; &nbsp; List<Object> states = testObject.getStates();&nbsp; &nbsp; &nbsp; &nbsp; for (Object object:states) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(object instanceof SimpleDto){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SimpleDto dto = (SimpleDto)object;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println(dto.getValue());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(object instanceof Integer){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Integer dto = (Integer)object;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println(dto);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return Optional.of(testObject);&nbsp; &nbsp; }有通用映射的 pojo 类public class TestObject implements Serializable {&nbsp; &nbsp; @JsonDeserialize(using = DynamicDeserializer.class)&nbsp; &nbsp; private List<Object> states;&nbsp; &nbsp; public List<Object> getStates() {&nbsp; &nbsp; &nbsp; &nbsp; return states;&nbsp; &nbsp; }&nbsp; &nbsp; public void setStates(List<Object> states) {&nbsp; &nbsp; &nbsp; &nbsp; this.states = states;&nbsp; &nbsp; }}对象列表的输入有效负载{&nbsp; "states": [&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; "label": "1",&nbsp; &nbsp; &nbsp; "value": 0&nbsp; &nbsp; }&nbsp; ]}整数列表的输入有效负载{&nbsp; "states": [&nbsp; &nbsp; &nbsp; 1,2&nbsp; ]}

慕的地8271018

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

繁星coding

写一个dtopublic class FooDTO {&nbsp; &nbsp; public Integer id;&nbsp; &nbsp; public String label;&nbsp; &nbsp; public Double amount;&nbsp; &nbsp; public List<Object> states;}在 Service 类中对 DTO 进行类型转换并处理异常

蝴蝶刀刀

您可以尝试完全重新设计架构。使用相关集合拆分主实体。提供独立服务来为您的实体添加/删除/设置状态。通过这种方式,您可以轻松地为您的客户端提供 REST 服务,使用起来一目了然。这是一组可能的方法,通过 REST 接口实现:@Path(../foo)@Producespublic interface FooService {&nbsp; //CRUD methods on Foo itself which work with attributes of Foo only&nbsp; ...&nbsp; @GET&nbsp; @Path("/{fooId}")&nbsp; FooDTO findById(@PathParam("fooId") int fooId);&nbsp; //status-related methods:&nbsp; @GET&nbsp; @Path("/{fooId}/status")&nbsp; List<SimpleDto> statuses(@PathParam("fooId") int fooId);&nbsp; @Post&nbsp; @Path("/{fooId}/status")&nbsp; void addStatus(@PathParam("fooId") int fooId, int statusId);&nbsp; @DELETE&nbsp; @Path("{fooId}/status")&nbsp; void deleteStatus(@PathParam("fooId") int fooId, int statusId);&nbsp; @PUT&nbsp; @Path("/status")&nbsp; void setStatuses(@PathParam("fooId") int fooId, List<Integer> newStatuses);}有了这个解决方案,还有一些替代选项,我更愿意返回:&nbsp; @GET&nbsp; @Path("/{fooId}/status")&nbsp; List<Integer> statuses(@PathParam("fooId") int fooId);而不是 DTO 列表。然后将提供一项服务来获取所有状态及其名称,而无需连接到 Foo:public interface StatusService {&nbsp; List<SimpleDto> statuses();}为了简化 GUI 组件的实现,您可以创建将返回组合数据的 Rest 服务,就像在您的第二个 FooDto 版本中一样。它还将减少休息电话的数量。但是拥有单独的方法来直接处理项目集合会很有帮助。
随时随地看视频慕课网APP

相关分类

Java
我要回答