在SpringMVC的上下文中,如何使用提供同一类的不同JSON表示的Web服务?

我有一个数据类,如下所示:

public class Person { private String name; private Long code; // corresponding getters and setters } 

我想编写两个Web服务,它们提供两种不同的JSON表示forms。 例如,其中一个提供{"name":"foo"}但另一个提供{"name":"foo", "code":"123"}

作为一个更复杂的场景,假设Person有一个引用属性,例如address。 地址也有自己的属性,我希望我的两个Web服务都考虑这个属性,但每个属性都以自己的方式执行。

我的SpringMVC视图应该如何?

请注意,我是SpringMVC的新手。 请在答案旁边给我一个示例代码。

更新1:几天后,所有答案都促使我解决控制器中的问题或通过注释数据类。 但是我希望在视图中执行此操作,而不再使用java代码。 我可以在JSP文件或百万美元模板甚至.properties文件中执行此操作吗?

更新2:我找到了json-taglib 。 但不知何故,它被排除在新的升级之外。 有没有类似的解决方案?

您正在使用Spring-MVC因此Jackson负责JSON序列化和反序列化。

在这种情况下,您可以使用@JsonInclude(Include.NON_NULL)在序列化期间忽略空字段。

 public class Person { @JsonInclude(Include.NON_NULL) private String name; @JsonInclude(Include.NON_NULL) private Long code; // corresponding getters and setters } 

如果您的namecodenull则它将从输出JSON排除

因此,如果您将code作为null传递,则您的输出JSON将看起来像{"name":"foo"}

在使用Spring MVC创建JSon时,默认情况下,“视图渲染器”是Jackson。 不需要使用JSP或其他视图技术。 你想要做的是告诉jackson如何为特定情况渲染一个物体。 有多种选择,但我建议使用预测。 一个例子:

 @RestController @RequestMapping(value = "person") public class PersonController { private final ProjectionFactory projectionFactory; public PersonController(ProjectionFactory projectionFactory) { this.projectionFactory = projectionFactory; } @GetMapping("...") public PersonBase getPerson(..., @RequestParam(value = "view", required = false, defaultValue = "base") String view) { ... if(view.equals("extended")) { return projectionFactory.createProjection(PersonExtended.class, person); } else { return projectionFactory.createProjection(PersonBase.class, person); } } } public interface PersonBase { String getName(); } public interface PersonExtended extends PersonBase { Long getCode; } 

应用程序的视图层是投影类(然后放在一个包中,视图包,如果你愿意的话)。 Controller可以选择要渲染的视图,也可以像示例中那样使结果动态化。

关于如何渲染地址的问题可以通过这样的另一个投影来解决:

 public interface PersonWithAddress extends PersonExtended { AddressProjection getAddress(); } public interface AddressProjection { String getStreetName(); String getZipcode(); ... } 

您可以使用MappingJacksonValue查找字段的动态过滤。

filter允许您序列化符合自定义条件的字段。

您可以在此处查看我的示例代码:

 package com.github.tddiaz.jsonresponsefiltering; import com.fasterxml.jackson.annotation.JsonFilter; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import jdk.nashorn.internal.objects.annotations.Getter; import lombok.Data; import lombok.NonNull; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.json.MappingJacksonValue; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @RestController class Controller { @GetMapping("/filter") public ResponseEntity filter() { final Response response = new Response("value1", "value2", "value3"); //ignore field3; will only return values of field1 and field2 final SimpleBeanPropertyFilter beanPropertyFilter = SimpleBeanPropertyFilter.filterOutAllExcept("field1", "field2"); final FilterProvider filterProvider = new SimpleFilterProvider().addFilter("responseFilter", beanPropertyFilter); final MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(response); mappingJacksonValue.setFilters(filterProvider); return ResponseEntity.ok(mappingJacksonValue); } } @JsonFilter("responseFilter") @Data class Response { @NonNull private String field1, field2, field3; } } 

如果您需要通过投影向此模型添加更多信息,请使用Projection以不同的方式显示您的json和ResourceProcessor,例如,可能是另一个DB表。

根据您的使用案例,只需从jsp / js页面调用您选择的控制器…例如,让我们说Admin是用户然后调用AdminController,然后调用User Controller …这可以使用简单的if / else来完成条件…你也可以查看代理设计模式,但这取决于用例

我建议你在前端使用JSON.stringify(value [,replacer [,space]])函数。 我在下面给出了一个例子。 您可以根据特定视图的要求编写自定义函数。

例如。 以下示例忽略空值。 这里我编写了editperson函数,它删除了空值。

该函数有两个输入参数,即键和值。 根据要删除或更改的键和值编写逻辑。

 var springperson = { "name":"foo","code":null } console.log(springperson); // person recieved from spring function editjson(key, value){ if (value !== null) return value } var editperson = JSON.stringify(springperson, editjson); // String representation of person var personjson=JSON.parse(editperson); // JSON object representation of person console.log(personjson); // person as required by the view