英文:
How to return required parameters as json response from pojo class in spring boot?
问题
我尝试做的是,
如果我拿一个像这样的pojo类
@Entity
@Table(name = "property_table")
public class Property {
@Id
@Column(name = "property_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int propertyId;
@Column(name = "property_name")
private String propertyName;
@Column(name = "property_type")
private String propertyType;
}
在RestController中,我编写了两个方法,像这样
@GetMapping(value = "/getProperties", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
@ResponseBody
public List<Property> getProperties() {
// some code
}
@GetMapping(value = "/getPropertyById", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
@ResponseBody
public Property getPropertyById() {
// some code
}
所以,我在尝试做的是
对于第一个api方法,我想返回类似从Property pojo类中的一些参数的json,即像
**对于getProperties api方法**
{
"property": [
{
"propertyId": 001,
"propertyName": "PROPERTY 1"
},
{
"propertyId": 002,
"propertyName": "PROPERTY 2"
}
]
},
在上面的json中,我只想返回两个参数,即propertyId,propertyName,而我不想在json中返回剩余的参数propertyType。
如何实现这样的返回?
对于第二个api方法,我想返回所有三个参数。即,像下面这样
**对于getPropertyById api方法**
{
"propertyId": 001,
"propertyName": "PROPERTY 1",
"propertyType": "PROPERTY_TYPE 1"
},
如何在不同的api方法中使用相同的pojo类返回不同的参数来维护不同的json响应。
请帮助我解决这个问题。谢谢。
英文:
what I am trying to do is,
If I take one pojo class like
@Entity
@Table(name = "property_table")
public class Property {
@Id
@Column(name = "property_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int propertyId;
@Column(name = "property_name")
private String propertyName;
@Column(name = "property_type")
private String propertyType;
}
In RestController I wrote Two Methods like
@GetMapping(value = "/getProperties", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
@ResponseBody
public List<Property> getProperties() {
//some code
}
@GetMapping(value = "/getPropertyById", produces = { "application/json",
"application/xml" }, consumes = { "application/xml", "application/json" })
@ResponseBody
public Property getPropertyById() {
//some code
}
So, hear what I am trying to do is
for first api method I want return json like some parameters from Property pojo class i.e., like
for getProperties api method
{
"property":[
{
"propertyId":001,
"propertyName":"PROPERTY 1"
},
{
"propertyId":002,
"propertyName":"PROPERTY 2"
}
],
In the Above json I want to return only two parameters i.e propertyId,propertyName and remaining parameter i.e propertyType I dont want to retun in json.
How to return like that?
and for the second api method I want to return all three parameters. i.e., like below
for getPropertyById api method
{
"propertyId":001,
"propertyName":"PROPERTY 1",
"propertyType:"PROPERTY_TYPE 1"
},
how to maintain different json response using same pojo class with different parameters for different api methods.
please help me to solve this isuue.
Thanks.
答案1
得分: 1
REST API的过度/不足获取是一个众所周知的问题。只有两种经典的处理方法。
第一种方法是针对每个属性可见性状态构建一个模型。因此,在您的情况下,您需要创建两个不同的模型(这种模型称为DTO - 数据传输对象)。一个模型将有一个propertyType
属性,另一个则没有。您分享的Property
模型显示您将同一类用作实体和传输对象。这种解决方案会为您的应用程序增加一些复杂性,因为您将不得不实现一些映射器,将实体转换为相应的DTO。
第二种方法是接受您发送一个不会有用的属性(要注意过度获取)。这种解决方案通常是最常采用的。这种解决方案的缺点是当您不想向客户端发送某些内容时(想象一个User
模型,您想要从客户端获取密码,但您不想将其发送回客户端)。另一个明显的负面点是事务会变大,但在大多数情况下可以忽略不计。
英文:
REST API under/over-fetching is a well-known problem. There's only two (classical ways) to handle that.
The first one is to build one model per each attribute visibility state. So, in your case, you'll need to create two different models (this kind of models are called DTO - Data Transfert Object). One model will have a propertyType
attribute, the other will not. The model Property
you've shared shows that you use the same class as entity and as transfert object. This solution will add some complexity to your app because you will have to implement some mappers to convert your entity to a corresponding DTO.
The second one is to accept that you send an attribute that will not be useful (be aware of the over-fetching). This solution is often the most adopted one. The cons of this solution is when you don't want to send something to your client (imagine a User
model, you want to get the password from your client but you don't want to sent it back to it). Another obvious negative point is that the transactions will be larger but it is negligible in most cases
答案2
得分: 0
我强烈建议您将@Entity
保持在'db'层中隔离。这样,数据库端的更改不会影响您的API,反之亦然。此外,您将能够更好地控制在您的API中公开哪些数据。根据您的需求,您可以创建2个真正的DTO,比如PropertyDto
和PropertyDetailsDto
(或者使用私有字段和getter/setter)。
public class PropertyDto {
public String propertyId;
public String propertyName;
}
public class PropertyDetailsDto extends PropertyDto {
public String propertyType;
}
将您的@Entity
映射到与您需求相对应的特定DTO。
编辑:
public List<PropertyDto> getProperties() {
return toPropertyDtos(repository.findAll());
}
public PropertyDetailsDto getPropertyById(Long id) {
return toPropertyDetailsDto(repository.findBy(id));
}
在某个Mapper.java
中:
...
public static List<PropertyDto> toPropertyDtos(List<Property> properties) {
return properties.stream()
.map(Mapper::toPropertyDto)
.collect(toList());
}
private static PropertyDto toPropertyDto(Property property) {
PropertyDto dto = new PropertyDto();
dto.propertyId = property.propertyId;
dto.propertyName = property.propertyName;
return dto;
}
// `toPropertyDetailsDto`的内容类似,您可以将通用映射部分提取到`Mapper`内部的单独私有方法中
...
英文:
I would strongly advice you to keep your @Entity
isolated in the 'db' layer. So that changes on the database side don't affect your API and vice versa. Also, you will have much better control over what data is exposed in your API. For your needs you can create 2 true DTOs, like PropertyDto
and PropertyDetailsDto
(or using private fields and getters/setters).
public class PropertyDto {
public String propertyId;
public String propertyName;
}
public class PropertyDetailsDto extends PropertyDto {
public String propertyType;
}
Map your @Entity
to a specific dto corresponding to your needs.
EDIT
public List<PropertyDto> getProperties() {
return toPropertyDtos(repository.findAll());
}
public PropertyDetailsDto getPropertyById(Long id) {
return toPropertyDetailsDto(repository.findBy(id));
}
in some Mapper.java
...
public static List<PropertyDto> toPropertyDtos(List<Property> properties) {
return properties.stream()
.map(Mapper::toPropertyDto)
.collect(toList());
}
private static PropertyDto toPropertyDto(Property property) {
PropertyDto dto = new PropertyDto();
dto.propertyId = property.propertyId;
dto.propertyName = property.propertyName;
return dto;
}
// same stuff for `toPropertyDetailsDto`, you could extract common mapping parts in a separate private method inside `Mapper`
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论