我有一个数据类,如下所示:
public class Person {
private String name;
private Long code;
// corresponding getters and setters
}
我想编写两个Web服务,它们提供Person的两个不同的JSON表示。例如,其中一个提供{"name":"foo"}
但另一个提供{"name":"foo", "code":"123"}
。
作为一个更复杂的场景,假设Person有一个引用属性,例如address。地址也有自己的属性,我希望我的两个Web服务都考虑这个属性,但每个属性都以自己的方式执行。
我的SpringMVC视图应该如何?
请注意我是SpringMVC的新手。请在答案旁边给我一个示例代码。
更新1:几天后,所有答案都促使我解决控制器中的问题或通过注释数据类。但我希望在视图中执行此操作,而不再使用java代码。我可以在JSP文件或百万美元模板甚至是.properties文件中进行吗?
更新2:我找到了json-taglib。但不知何故,它被排除在新的升级之外。有没有类似的解决方案?
答案 0 :(得分:5)
您正在使用Spring-MVC
,因此杰克逊负责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
}
如果您的name
或code
为null
,则会将其排除在输出JSON
因此,如果您将code
作为null
传递,则您的输出JSON将显示为{"name":"foo"}
答案 1 :(得分:4)
您可以使用MappingJacksonValue
查找字段的动态过滤。
过滤器允许您序列化符合自定义条件的字段。
您可以在此处查看我的示例代码:
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;
}
}
答案 2 :(得分:4)
使用Spring MVC创建JSon时,默认情况下,"视图渲染器"是Jackson。不需要使用JSP或其他视图技术。你想要做的是告诉杰克逊如何为特定情况渲染一个物体。有多种选择,但我建议使用预测。 一个例子:
@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();
...
}
答案 3 :(得分:2)
如果您需要通过投影向此模型添加更多信息,请使用Projection以不同方式公开您的json和ResourceProcessor,例如,可能是另一个DB表。
答案 4 :(得分:2)
根据您的使用案例,只需从jsp / js页面调用您选择的控制器...例如让我们说管理员是用户然后调用AdminController,否则调用用户控制器...这可以使用简单的if / else条件来完成...你也可以查看代理设计模式,但这取决于用例< / p>
答案 5 :(得分:2)
我建议你在前端使用 JSON.stringify(value [,replacer [,space]])函数。我在下面给出了一个例子。您可以根据特定视图的要求编写自定义函数。
EG。以下示例忽略空值。这里我编写了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
评论您是否有任何问题。