Spring boot Jackson反序列化错误。调用不需要的外部字段

问题描述 投票:0回答:1

我正在尝试创建一个接受“食物”项目并保存它的 post 方法。食品实体有两个外国字段,称为“餐厅”和“菜单”。当我发送请求时,由于某种原因,Spring boot 尝试从菜单对象访问餐厅的 id 字段。我该如何修复这个错误?

这是我的实体。

@Entity
@Getter
@Setter
@NoArgsConstructor
@JsonSerialize(using = MenuSerializer.class)
public class Menu {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "restaurant_id", nullable = false)
    @JsonIgnore
    private Restaruant restaurant;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinColumn(name = "menu_id")
    private List<Food> foods = new ArrayList<Food>();

    @Override
    public String toString() {
        return "Menu [id=" + id + ", name=" + name + ", restaurant=" + restaurant + ", foods=" + foods + "]";
    }

    
}
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Food {
    
    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY)
    private Long Id;
    private String name;
    private String picture;
    private Double price;
    
    @Column(columnDefinition = "text")
    private String description;
    private String category;
    private Double discount;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "menu_id", nullable = false)
    @JsonIncludeProperties({"id"})
    private Menu menu;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "restaurant_id", nullable = false)
    @JsonIncludeProperties({"id"})
    private Restaruant restaurant;
    
    @OneToMany(mappedBy = "food")
    @JsonIgnore
    private List<CartItem> cartItems = new ArrayList<>();

    private Boolean available;

    @Override
    public String toString() {
        return "Food [Id=" + Id + ", name=" + name + ", picture=" + picture + ", price=" + price + ", description="
                + description + ", category=" + category + ", discount=" + discount + ", menu=" + menu + ", restaurant="
                + restaurant + ", cartItems=" + cartItems + ", available=" + available + "]";
    }
    
    
}
@Entity
@Setter
@Getter
@NoArgsConstructor
public class Restaruant {
    
    @Id
    @GeneratedValue ( strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String profile;
    private Boolean available;
    @Column(columnDefinition = "text")
    private String description;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "owner_id")
    @JsonIgnore
    private User owner;
    
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "address_id", referencedColumnName = "id")
    @JsonIgnore
    private Address address;
    
    @ManyToOne
    @JoinColumn(name = "region_id")
    @JsonIgnore
    private Region region;
     
}

这是我的控制器方法。这里没有什么特别的。

@PostMapping("/create")
    public ResponseEntity<Food> createFood(@RequestBody Food food, Principal principal) {
        
        //restaurantService.validateRestaurantOwner(food.getRestaurant().getId(), principal.getName());
        System.out.println(food);
        
        Food createdFood = foodService.saveFood(food);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdFood);
    }

我在保存之前打印了食物对象,以便我可以看到它是什么样子。

Food [Id=null, name=jkla;f, picture=null, price=10.0, description=ffff, category=jfla, discount=1.0, menu=Menu [id=3, name=null, restaurant=null, foods=[]], restaurant=com.hostmdy.food.domain.Restaruant@4c91c71a, cartItems=[], available=true]

这个物体正是我所期望的。不知道是不是有什么问题。 这是我收到的错误消息。

[2m2024-09-10T18:01:34.590+06:30[0;39m [33m WARN[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "com.hostmdy.food.domain.Restaruant.getId()" because the return value of "com.hostmdy.food.domain.Menu.getRestaurant()" is null]

Spring 正在尝试访问 Menu.getRestaurant()。它不应该这样做。

我还打印了所有调试行,以防你们想看。

Executing identity-insert immediately
[2m2024-09-10T18:01:34.546+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.SQL                       [0;39m [2m:[0;39m insert into food (available,category,description,discount,menu_id,name,picture,price,restaurant_id,id) values (?,?,?,?,?,?,?,?,?,default)
[2m2024-09-10T18:01:34.548+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.orm.results               [0;39m [2m:[0;39m Initializer list is empty
[2m2024-09-10T18:01:34.548+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.orm.results.loading       [0;39m [2m:[0;39m Calling top-level assembler (0 / 1) : org.hibernate.sql.results.graph.basic.BasicResultAssembler@7d41471c
[2m2024-09-10T18:01:34.548+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.orm.results               [0;39m [2m:[0;39m Extracted JDBC value [0] - [7]
[2m2024-09-10T18:01:34.551+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.id.IdentifierGeneratorHelper        [0;39m [2m:[0;39m Extracted generated values [com.hostmdy.food.domain.Food]: [Ljava.lang.Object;@643eaf3f
[2m2024-09-10T18:01:34.554+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.orm.jpa.JpaTransactionManager       [0;39m [2m:[0;39m Initiating transaction commit
[2m2024-09-10T18:01:34.555+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.orm.jpa.JpaTransactionManager       [0;39m [2m:[0;39m Committing JPA transaction on EntityManager [SessionImpl(610926081<open>)]
[2m2024-09-10T18:01:34.555+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.t.internal.TransactionImpl        [0;39m [2m:[0;39m committing
[2m2024-09-10T18:01:34.555+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener   [0;39m [2m:[0;39m Processing flush-time cascades
[2m2024-09-10T18:01:34.556+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener   [0;39m [2m:[0;39m Dirty checking collections
[2m2024-09-10T18:01:34.557+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.hibernate.engine.internal.Collections [0;39m [2m:[0;39m Collection found: [com.hostmdy.food.domain.Food.cartItems#7], was: [<unreferenced>] (initialized)
[2m2024-09-10T18:01:34.558+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener   [0;39m [2m:[0;39m Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
[2m2024-09-10T18:01:34.558+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener   [0;39m [2m:[0;39m Flushed: 1 (re)creations, 0 updates, 0 removals to 1 collections
[2m2024-09-10T18:01:34.565+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.hibernate.internal.util.EntityPrinter [0;39m [2m:[0;39m Listing entities:
[2m2024-09-10T18:01:34.567+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.hibernate.internal.util.EntityPrinter [0;39m [2m:[0;39m com.hostmdy.food.domain.Food{price=10.0, restaurant=com.hostmdy.food.domain.Restaruant#1, available=true, name=jkla;f, description=ffff, discount=1.0, Id=7, cartItems=[], category=jfla, menu=com.hostmdy.food.domain.Menu#3, picture=null}
[2m2024-09-10T18:01:34.568+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.orm.jpa.JpaTransactionManager       [0;39m [2m:[0;39m Not closing pre-bound JPA EntityManager after transaction
[2m2024-09-10T18:01:34.579+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.w.s.m.m.a.HttpEntityMethodProcessor [0;39m [2m:[0;39m Using 'application/json', given [*/*] and supported [application/json, application/*+json]
[2m2024-09-10T18:01:34.580+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.w.s.m.m.a.HttpEntityMethodProcessor [0;39m [2m:[0;39m Writing [Food [Id=7, name=jkla;f, picture=null, price=10.0, description=ffff, category=jfla, discount=1.0, me (truncated)...]
[2m2024-09-10T18:01:34.590+06:30[0;39m [33m WARN[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "com.hostmdy.food.domain.Restaruant.getId()" because the return value of "com.hostmdy.food.domain.Menu.getRestaurant()" is null]
[2m2024-09-10T18:01:34.590+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.j.s.OpenEntityManagerInViewInterceptor[0;39m [2m:[0;39m Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
[2m2024-09-10T18:01:34.593+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet       [0;39m [2m:[0;39m Completed 500 INTERNAL_SERVER_ERROR

我还尝试创建自定义解串器,但它仍然不起作用。

spring-boot spring-mvc spring-data-jpa jackson jsonserializer
1个回答
0
投票

问题来自

@JsonIncludeProperties({"id"})
。因此它会尝试序列化该属性。

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "restaurant_id", nullable = false)
    @JsonIncludeProperties({"id"}) //this
    private Restaruant restaurant;

您可以通过从

Food
中删除这些注释来修复它。如果另一个控制器依赖于此,我建议您使用
@JsonView
根据上下文进行不同的序列化。

© www.soinside.com 2019 - 2024. All rights reserved.