Java show/hide 对象字段取决于 REST 调用
Java show/hide object fields depending on REST call
是否可以根据 REST 调用配置项目 class 以显示和隐藏特定字段?
例如,我想在调用 XmlController
时从 User
class 隐藏 colorId
(并显示 categoryId
),而在调用 JsonController
时则相反。
项目class
@Getter
@Setter
@NoArgsConstructor
public class Item
{
private Long id;
private Long categoryId; // <-- Show field in XML REST call and hide in JSON REST call
private Long colorId; // <-- Show field in JSON REST call and hide in XML REST call
private Long groupId;
@JacksonXmlProperty(localName = "item")
@JacksonXmlElementWrapper(localName = "groupItems")
private List<GroupedItem> item;
}
JSON 控制器
@RestController
@RequestMapping(
path = "/json/",
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class JsonController
{
@Autowired
private Service service;
@RequestMapping(path = "{colorId}")
public Item getArticles(@PathVariable("colorId") Long colorId)
{
return service.getByColor(colorId); // returns JSON without "categoryId"
}
}
XML 控制器
@RestController
@RequestMapping(
path = "/xml/",
produces = MediaType.APPLICATION_XML_VALUE)
public class XmlController
{
@Autowired
private Service service;
@RequestMapping(path = "{categoryId}")
public Item getArticles(@PathVariable("categoryId") Long categoryId)
{
return service.getByCategory(categoryId); // returns XML without "colorId"
}
}
是的,这可以使用 Jackson JSON Views 和方法 ObjectMapper#writerWithView
。
您只需要为两个控制器配置不同的 ObjectMapper
就可以了
Jackson JSON 视图的示例如下,我们注意到 ownerName
只能在内部访问,不能公开访问
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
我已经通过创建以下视图解决了这个问题:
public class View
{
public static class Parent
{
}
public static class Json extends Parent
{
}
public static class Xml extends Parent
{
}
}
使用此配置可以将 Class 设置为:
@Getter
@Setter
@NoArgsConstructor
@JsonView(View.Parent.class)
public class Item
{
private Long id;
@JsonView(View.Xml.class) // <-- Show field in XML REST call and hide in JSON REST call
private Long categoryId;
@JsonView(View.Json.class) // <-- Show field in JSON REST call and hide in XML REST call
private Long colorId;
private Long groupId;
@JacksonXmlProperty(localName = "item")
@JacksonXmlElementWrapper(localName = "groupItems")
private List<GroupedItem> item;
}
(注意:如果您想在回复中列出 List<GroupedItem> item
,您还需要在 GroupedItem
中定义 @JsonView(View.Parent.class)
)
最后,如果您使用 Spring,REST 请求(参见问题)可以定义为:
@JsonView(View.Json.class) // or @JsonView(View.Xml.class) in other case
@RequestMapping(path = "{colorId}")
public Item getArticles(@PathVariable("colorId") Long colorId)
{
return service.getByColor(colorId); // returns JSON without "categoryId"
}
是否可以根据 REST 调用配置项目 class 以显示和隐藏特定字段?
例如,我想在调用 XmlController
时从 User
class 隐藏 colorId
(并显示 categoryId
),而在调用 JsonController
时则相反。
项目class
@Getter
@Setter
@NoArgsConstructor
public class Item
{
private Long id;
private Long categoryId; // <-- Show field in XML REST call and hide in JSON REST call
private Long colorId; // <-- Show field in JSON REST call and hide in XML REST call
private Long groupId;
@JacksonXmlProperty(localName = "item")
@JacksonXmlElementWrapper(localName = "groupItems")
private List<GroupedItem> item;
}
JSON 控制器
@RestController
@RequestMapping(
path = "/json/",
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class JsonController
{
@Autowired
private Service service;
@RequestMapping(path = "{colorId}")
public Item getArticles(@PathVariable("colorId") Long colorId)
{
return service.getByColor(colorId); // returns JSON without "categoryId"
}
}
XML 控制器
@RestController
@RequestMapping(
path = "/xml/",
produces = MediaType.APPLICATION_XML_VALUE)
public class XmlController
{
@Autowired
private Service service;
@RequestMapping(path = "{categoryId}")
public Item getArticles(@PathVariable("categoryId") Long categoryId)
{
return service.getByCategory(categoryId); // returns XML without "colorId"
}
}
是的,这可以使用 Jackson JSON Views 和方法 ObjectMapper#writerWithView
。
您只需要为两个控制器配置不同的 ObjectMapper
就可以了
Jackson JSON 视图的示例如下,我们注意到 ownerName
只能在内部访问,不能公开访问
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
我已经通过创建以下视图解决了这个问题:
public class View
{
public static class Parent
{
}
public static class Json extends Parent
{
}
public static class Xml extends Parent
{
}
}
使用此配置可以将 Class 设置为:
@Getter
@Setter
@NoArgsConstructor
@JsonView(View.Parent.class)
public class Item
{
private Long id;
@JsonView(View.Xml.class) // <-- Show field in XML REST call and hide in JSON REST call
private Long categoryId;
@JsonView(View.Json.class) // <-- Show field in JSON REST call and hide in XML REST call
private Long colorId;
private Long groupId;
@JacksonXmlProperty(localName = "item")
@JacksonXmlElementWrapper(localName = "groupItems")
private List<GroupedItem> item;
}
(注意:如果您想在回复中列出 List<GroupedItem> item
,您还需要在 GroupedItem
中定义 @JsonView(View.Parent.class)
)
最后,如果您使用 Spring,REST 请求(参见问题)可以定义为:
@JsonView(View.Json.class) // or @JsonView(View.Xml.class) in other case
@RequestMapping(path = "{colorId}")
public Item getArticles(@PathVariable("colorId") Long colorId)
{
return service.getByColor(colorId); // returns JSON without "categoryId"
}