Spring对象映射器covertValue方法不会转换某些字段

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

我有一个Spring Boot 2应用程序,它使用ObjectMapper.convertValue方法在实体和DTO之间进行转换。

我一直试图理解为什么该方法不能转换某些字段,特别是请看以下情况:

产品实体:

@Entity
@Table(name = "product")
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@AllArgsConstructor
public class Product extends AbstractPersistable<Long> {

    @Column
    private String name;

    @Column
    private String description;

    @Column
    private BigDecimal price;

    @Column
    private int weight;

    @Column
    private int stock = 0;

    @Column(name = "image_url", length = 254, unique = true)
    private String imageUrl;

    @NotEmpty
    @Column(name = "banner_image_url", length = 254, unique = true)
    private String bannerImageUrl;

    @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "product_category_id")
    @JsonBackReference
    private Category category;

    @OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @OrderBy
    @JsonManagedReference
    private SortedSet<ProductThumbnail> thumbnails;

    public Product(Long id) {
        this.setId(id);
    }

    public Product(String name, String description, BigDecimal price, int weight) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.weight = weight;
    }
}

产品DTO:

@Getter
@Setter
@NoArgsConstructor
public class ProductDTO {

    private Long id;

    private String name;

    private String description;

    private BigDecimal price;

    private int weight;

    private String imageUrl;

    private String bannerImageUrl;

    private CategoryDTO category;

    private SortedSet<ProductThumbnailDTO> thumbnails;

    public ProductDTO(@JsonProperty("id") Long id) {
        this.id = id;
    }

    @JsonCreator
    public ProductDTO(@JsonProperty("id") Long id,
                      @JsonProperty("name") String name,
                      @JsonProperty("description") String description,
                      @JsonProperty("price") BigDecimal price,
                      @JsonProperty("weight") int weight,
                      @JsonProperty("imageUrl") String imageUrl,
                      @JsonProperty("category") CategoryDTO category,
                      @JsonProperty("variants") Set<ProductVariantDTO> variants) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.price = price;
        this.weight = weight;
        this.imageUrl = imageUrl;
        this.category = category;
        this.variants = variants;
    }
}

执行字段代码时每个字段都会自动转换:

ProductDTO productDTO = objectMapper.convertValue(product,ProductDTO.class);

category除外。因此,在product变量中设置了类别,而转换后结果productDTO.category字段为null。

类别实体:

@Entity
@Table(name = "product_category")
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@AllArgsConstructor
@Immutable
public class Category extends AbstractPersistable<Long> {

    @Column
    private String name;

    @Column
    private String description;

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonManagedReference
    private Set<Product> products = new HashSet<>();
}

类别DTO:

@Data
@NoArgsConstructor
public class CategoryDTO {

    private String name;

    private String description;

    @JsonIgnore
    private Set<Product> products = new HashSet<>();

    @JsonCreator
    public CategoryDTO(@JsonProperty("name") String name, @JsonProperty("description") String description) {
        this.name = name;
        this.description = description;
    }
}

所以问题是,为什么ObjectMapper也不能自动转换类别字段?是否有阻止这种情况发生的条件?因为根本不会引发任何错误。

下面是objectmapper bean:

@Bean
public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.findAndRegisterModules();
    objectMapper.registerModules(module(), new Jdk8Module());
    return objectMapper;
}

杰克逊Dep版本2.10.1

UPDATE1:

根据下面的图片对输入产品实体变量进行赋值:

enter image description here

虽然转换后的产品如下(转换后您看到类别为空):

enter image description here

谢谢

java spring spring-boot jackson objectmapper
1个回答
0
投票

因此,您代码中的主要罪魁祸首是@JsonBackReference。由于@JsonBackReference注释已分配给

    @JsonBackReference
    private Category category;

此类别在序列化时会自动删除。来自this reference:

@@ JsonManagedReference是参考的前一部分–通常被序列化的参考。@JsonBackReference是参考的后半部分–序列化将忽略它。

因此而不是@JsonBackReference,请尝试使用:@JsonManagedReference

希望这可以解决您的问题。

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