java - 使用 @JsonView 的 Spring Json-Serialization 返回关联的空对象

标签 java spring-boot json-serialization

我有一个带有 JPA 和 JSON 序列化的 Spring-Boot-Project。我尝试使用 @JsonView 仅序列化指定的属性。它工作正常,但对于我在 Order 中的关联(例如 order.user),它序列化了空 Json 对象。

我使用以下依赖项

  • Spring-Boot 2.0.1.RELEASE
  • Spring-Boot-Starter-JPA 2.0.1.RELEASE
  • Spring-Hateos 0.24.0.RELEASE

查看以下 Json 结果:

{
  "content" : {
    "orderResources" : [ {
      "receiptDate" : "2019-08-14",
      "state" : "BILL_CREATED",
      "user" : { },
      "employer" : { },
      "orderplace" : { },
      "propertyManagement" : null,
      "plannings" : [ { } ]
    }, {
      "receiptDate" : "2019-08-17",
      "state" : "BILL_CREATED",
      "user" : { },
      "employer" : { },
      "orderplace" : { },
      "propertyManagement" : null,
      "plannings" : [ ]
    } ]
  },
  "links" : {
    "next" : {
      "href" : "https://orderbook-demo.localhost:8443/api/order?page=1"
    },
    "1" : {
      "href" : "https://orderbook-demo.localhost:8443/api/order?page=1"
    }
  },
  "page" : {
    "size" : 6,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  }
}

我的实体

订单

@Entity
@JsonRootName("Order")
@BatchSize(size = 100 )
@Table(name="`order`")
@Access(AccessType.FIELD)
public class Order extends BaseEntity {

    private static final long serialVersionUID = 1L;

    @Column(name="receipt_date", nullable = false)
    @Type(type = "de.orderbook.hibernate.type.LocalDateUserType")
    @JsonSerialize(using = LocalDateJsonSerializer.class)
    @JsonDeserialize(using = LocalDateJsonDeserializer.class)
    @JsonProperty
    @JsonView(View.ListView.class)
    private LocalDate receiptDate;

    @Column(name="state", nullable = false)
    @Enumerated(value = EnumType.STRING)
    @JsonProperty
    @JsonView(View.ListView.class)
    private State state = State.OPEN;

    @ManyToOne
    @JoinColumn(name = "offer_id")
    @JsonProperty
    @JsonIgnore
    private Offer offer;

    @OneToMany(targetEntity = OrderOrderdetail.class, mappedBy = "order", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn
    @BatchSize(size = 100)
    @JsonProperty
    private List<OrderOrderdetail> orderdetails = new ArrayList<>(10);

    @ManyToOne(targetEntity = Address.class, cascade = CascadeType.ALL)
    @JoinColumn(name= "employer_id")
    @Fetch(FetchMode.SELECT)
    @BatchSize(size = 100)
    @JsonProperty
    @JsonView(View.ListView.class)
    private Address employer;

    @ManyToOne(targetEntity = Address.class, cascade = CascadeType.ALL)
    @JoinColumn(name= "orderplace_id")
    @Fetch(FetchMode.SELECT)
    @BatchSize(size = 100)
    @JsonProperty
    @JsonView(View.ListView.class)
    private Address orderplace;

    @ManyToOne(targetEntity = Address.class, cascade = CascadeType.ALL)
    @JoinColumn(name= "property_management_id")
    @Fetch(FetchMode.SELECT)
    @BatchSize(size = 100)
    @JsonProperty
    @JsonView(View.ListView.class)
    private Address propertyManagement;

    @ManyToOne
    @JoinColumn(name="user_id")
    @BatchSize(size = 100 )
    @JsonProperty
    @JsonView(View.ListView.class)
    private User user;

    @OneToMany(targetEntity = Planning.class, mappedBy = "order", cascade = CascadeType.ALL)
    @BatchSize(size = 100 )
    @JsonProperty
    @JsonView(View.ListView.class)
    private List<Planning> plannings = new ArrayList<Planning>(3);

    public Order() {
        super();
    }

    public Order(Offer offer) {
        super();
        this.receiptDate = LocalDate.now();
        this.employer = offer.getEmployer();
        this.orderplace = offer.getOrderplace();
        this.propertyManagement = offer.getPropertyManagement();
        this.user = offer.getUser();
        this.offer = offer;
        for (OfferOrderdetail orderdetail : offer.getOrderdetails()) {
            OrderOrderdetail orderOrderdetail = new OrderOrderdetail(orderdetail.getOrderdetail(), orderdetail.getCount());
            orderOrderdetail.setOrder(this);
            this.getOrderdetails().add(orderOrderdetail);
        }
    }

    @JsonCreator
    public Order(@JsonProperty("receiptDate") LocalDate receiptDate,
                 @JsonProperty("state") State state,
                 @JsonProperty("user") User user,
                 @JsonProperty("employer") Address employer,
                 @JsonProperty("orderplace") Address orderplace,
                 @JsonProperty("propertyManagement") Address propertyManagement,
                 @JsonProperty("orderdetails") List<OrderOrderdetail> orderdetails,
                 @JsonProperty("plannings") List<Planning> plannings
    ) {
        super();
        this.receiptDate = receiptDate;
        this.state = state;
        this.user = user;
        this.employer = employer;
        this.orderplace = orderplace;
        this.propertyManagement = propertyManagement;
        this.orderdetails = orderdetails;
        this.plannings = plannings;
    }

    public LocalDate getReceiptDate() {
        return receiptDate;
    }

    public void setReceiptDate(LocalDate receiptDate) {
        this.receiptDate = receiptDate;
    }

    public List<OrderOrderdetail> getOrderdetails() {
        return orderdetails;
    }

    public void setOrderdetails(List<OrderOrderdetail> orderdetails) {
        this.orderdetails = orderdetails;
    }

    public void addOrderdetail(OrderOrderdetail orderdetail) {
        this.orderdetails.add(orderdetail);
    }

    public void removeOrderdetail(OrderOrderdetail orderdetail) {
        this.orderdetails.remove(orderdetail);
    }

    public boolean containsOrderdetail(OrderOrderdetail orderdetail) {
        return this.orderdetails.contains(orderdetail);
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<Planning> getPlannings() {
        return plannings;
    }

    public void addPlanning(Planning planning) {
        this.plannings.add(planning);
    }

    public void removePlanning(Planning planning) {
        this.plannings.remove(planning);
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public Address getEmployer() {
        return employer;
    }

    public void setEmployer(Address employer) {
        this.employer = employer;
    }

    public Address getOrderplace() {
        return orderplace;
    }

    public void setOrderplace(Address orderplace) {
        this.orderplace = orderplace;
    }

    public Address getPropertyManagement() {
        return propertyManagement;
    }

    public void setPropertyManagement(Address propertyManagement) {
        this.propertyManagement = propertyManagement;
    }

    public void setPlannings(List<Planning> plannings) {
        this.plannings = plannings;
    }

    public Offer getOffer() {
        return offer;
    }

    public void setOffer(Offer offer) {
        this.offer = offer;
    }
}

用户

@Entity
@Table(name="`user`")
@JsonView(View.ListView.class)
public class User extends BaseEntity {

    private static final long serialVersionUID = 1L;

    @JsonProperty
    @JsonView(View.ListView.class)
    private String name;

    @NaturalId
    @JsonProperty
    @JsonView(View.ListView.class)
    private String username;

    @JsonProperty
    @JsonView(View.ListView.class)
    private String email;

    private @JsonIgnore String password;

    @JsonProperty
    @JsonView(View.ListView.class)
    private boolean enabled;

    @OneToMany(targetEntity = Authority.class)
    @JoinColumn(name = "username", referencedColumnName = "username")
    @BatchSize(size = 100)
    @JsonProperty
    @JsonView(View.ListView.class)
    private List<Authority> roles;

    public User() {
        super();
    }

    public User(String username, String name, String password, String email, boolean enabled, Authority... roles) {
        super();
        this.username = username;
        this.name = name;
        this.email = email;
        this.enabled = enabled;
        this.setPassword(password);
        this.roles = roles == null ? Collections.emptyList() : Arrays.asList(roles);
    }

    @JsonCreator
    public User(@JsonProperty("username") String username, @JsonProperty("name") String name, @JsonProperty("email") String email, @JsonProperty("enabled") boolean enabled, @JsonProperty("roles") List<Authority> roles) {
        super();
        this.username = username;
        this.name = name;
        this.email = email;
        this.enabled = enabled;
        this.roles = roles == null ? Collections.emptyList() : roles;
    }

    public User(String username) {
        super();
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Authority> getRoles() {
        return roles;
    }

    public void setRoles(List<Authority> roles) {
        this.roles = roles;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

我的 Controller

@Controller
public class OrderController extends BaseController<Order, OrderRepository> {

    private static int PAGE_SIZE = 6;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BillRepository billRepository;

    @Transactional
    @JsonView(View.ListView.class)
    @RequestMapping(value = "/api/order", method = RequestMethod.GET, headers = "content-type=application/json", consumes = "*/*", produces = "application/json")
    public @ResponseBody
    HttpEntity<OrderPagedResource> findAll(Principal principal, @RequestParam(name="page") Long page) {
        List<Order> list = super.list(page, Long.valueOf(PAGE_SIZE));

        for (Order order : list) {
            Hibernate.initialize(order.getPlannings());
            Hibernate.initialize(order.getUser().getRoles());
        }
        List<OrderResource> resources = new OrderResourceAssembler().toResources(list);
        Long count = this.repository.count();
        return new HttpEntity<OrderPagedResource>(new OrderPagedResource(resources, new MyPagedMetadata(PAGE_SIZE, page, count)));
    }
}

订单资源

public class OrderResource extends ResourceSupport {
    @JsonUnwrapped
    @JsonView(View.ListView.class)
    private Order content;

    public OrderResource(Order order) {
        super();
        this.content = order;
    }

    public Order getContent() {
        return content;
    }

    public void setContent(Order content) {
        this.content = content;
    }
}

订单页面资源

public class OrderPagedResource extends PagedResources<OrderResource> {
    private Map<String, MyLink> links = new HashMap(5);

    public OrderPagedResource(Collection<OrderResource> content, PageMetadata metadata) {
        super(content, metadata);
        for (int i = 1; i <= metadata.getTotalPages(); i++) {
            if (i == metadata.getNumber() - 1)
                this.links.put("prev", new MyLink(linkTo(OrderController.class).slash("/api/order?page=" + i).withRel("prev")));
            if (i == metadata.getNumber() + 1)
                this.links.put("next", new MyLink(linkTo(OrderController.class).slash("/api/order?page=" + i).withRel("next")));
            this.links.put(Integer.toString(i), new MyLink(linkTo(OrderController.class).slash("/api/order?page=" + i).withRel(Integer.toString(i))));
        }
    }

    @Override
    @JsonProperty("page")
    @JsonView(View.ListView.class)
    public PageMetadata getMetadata() {
        return super.getMetadata();
    }

    @Override
    @JsonProperty("content")
    @JsonView(View.ListView.class)
    public Collection<OrderResource> getContent() {
        return super.getContent();
    }

    @JsonProperty("links")
    @JsonView(View.ListView.class)
    public Map<String, MyLink> getLinks2() {
        return this.links;
    }

    public class MyLink extends Link {
        private @XmlAttribute @JsonProperty @JsonView(View.ListView.class) String rel;
        private @XmlAttribute @JsonProperty @JsonView(View.ListView.class) String href;

        public MyLink(Link link) {
            super(link.getHref(), link.getRel());
            this.rel = link.getRel();
            this.href = link.getHref();
        }
        public MyLink(String href) {
            super(href);
            this.href = href;
        }

        public MyLink(String href, String rel) {
            super(href, rel);
            this.href = href;
            this.rel = rel;
        }

        public MyLink() {
        }

        @Override
        @JsonView(View.ListView.class)
        public String getRel() {
            return this.rel;
        }

        @Override
        @JsonView(View.ListView.class)
        public String getHref() {
            return this.href;
        }
    }
}

订单资源组装器

@Component
public class OrderResourceAssembler extends ResourceAssemblerSupport<Order, OrderResource> {

    public OrderResourceAssembler() {
        super(OrderController.class, OrderResource.class);
    }

    @Transactional
    @Override
    public OrderResource toResource(Order entity) {
        OrderResource resource = new OrderResource(entity);

        resource.add(linkTo(OrderController.class).slash("/api/order/" + entity.getId()).withSelfRel());
        if (entity.getOffer() != null)
            resource.add(linkTo(OrderController.class).slash("/api/offer/" + entity.getOffer().getId()).withRel("offer"));
        resource.add(linkTo(UserController.class).slash("/api/user/" + entity.getUser().getId()).withRel("user"));

        return resource;
    }

}

最佳答案

默认情况下,Spring 不会将子对象中的属性包含到 @JsonView 中。您可以将 @JsonView 添加到子 POJO,或者通过应用以下配置来启用所有子属性。

spring.jackson.mapper.default-view-inclusion=true

关于java - 使用 @JsonView 的 Spring Json-Serialization 返回关联的空对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57927165/

相关文章:

java - 匹配器返回不匹配

java - 如何将元素添加到具有模型类型的列表中

arrays - RowMapper 的 Spring jdbc 模板的单元测试用例

json - 解析从 iOS swift 3 中的 lambda 返回的 AWSTask 响应

json - JSON中的反序列化和序列化是什么?

java - Jackson Json 到 POJO 的映射

java - 将大科学数转换为长数

java - Collection 和 map

JAVA ObjectNode 获取为空

Spring i18n : NoSuchMessageException: No message found under code 'welcome' for locale 'en_US'