如何从Spring Boot的POJO类中将所需参数以JSON响应的形式返回?

huangapple go评论59阅读模式
英文:

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中我只想返回两个参数即propertyIdpropertyName而我不想在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 = &quot;property_table&quot;)
public class Property {
@Id
@Column(name = &quot;property_id&quot;)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int propertyId;
@Column(name = &quot;property_name&quot;)
private String propertyName;
@Column(name = &quot;property_type&quot;)
private String propertyType;
}

In RestController I wrote Two Methods like

   @GetMapping(value = &quot;/getProperties&quot;, produces = { &quot;application/json&quot;,
&quot;application/xml&quot; }, consumes = { &quot;application/xml&quot;, &quot;application/json&quot; })
@ResponseBody
public List&lt;Property&gt; getProperties() {
//some code 
}
@GetMapping(value = &quot;/getPropertyById&quot;, produces = { &quot;application/json&quot;,
&quot;application/xml&quot; }, consumes = { &quot;application/xml&quot;, &quot;application/json&quot; })
@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

{
&quot;property&quot;:[
{
&quot;propertyId&quot;:001,
&quot;propertyName&quot;:&quot;PROPERTY 1&quot;
},
{
&quot;propertyId&quot;:002,
&quot;propertyName&quot;:&quot;PROPERTY 2&quot;
}
],

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

{
&quot;propertyId&quot;:001,
&quot;propertyName&quot;:&quot;PROPERTY 1&quot;,
&quot;propertyType:&quot;PROPERTY_TYPE 1&quot;
},

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,比如PropertyDtoPropertyDetailsDto(或者使用私有字段和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&lt;PropertyDto&gt; getProperties() {
return toPropertyDtos(repository.findAll());
}
public PropertyDetailsDto getPropertyById(Long id) {
return toPropertyDetailsDto(repository.findBy(id));
}
in some Mapper.java
...
public static List&lt;PropertyDto&gt; toPropertyDtos(List&lt;Property&gt; 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`

...

huangapple
  • 本文由 发表于 2020年10月9日 19:28:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/64279152.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定