Spring Boot使用MongoRepository存储动态JSON到MongoDB的结构调整问题
问题原因
你当前的实体类中product是独立的Map类型字段,Spring Data MongoDB默认会将其序列化为嵌套对象存储,因此会多出一层product结构。
解决方法
这里提供两种兼容动态字段需求的实现方案:
方案1:使用@Unwrapped注解(改动最小)
Spring Data MongoDB 3.2及以上版本提供了@Unwrapped注解,可直接将嵌套字段的属性平铺到文档根层级,只需修改Product实体类即可:
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Unwrapped; import org.springframework.data.annotation.Id; import java.util.Map; import java.util.HashMap; @Document public class Product { @Id private String id; @Unwrapped(onEmpty = Unwrapped.OnEmpty.USE_NULL) private Map<String,Object> product; public Product(){ this.product = new HashMap<>(); } public void setProduct(Map<String,Object> product){ this.product = product; } public Map<String, Object> getProduct(){ return this.product; } // id的getter、setter public String getId() { return id; } public void setId(String id) { this.id = id; } }
修改后原有控制器逻辑不需要做任何调整,存储时会自动将product Map内的所有键值对平铺到根层级。
方案2:手动转换存储(兼容性最好)
如果你使用的Spring Data MongoDB版本低于3.2,或者不想依赖特定注解,可以通过手动转换的方式实现,逻辑更透明:
- 首先修改Product实体类,继承HashMap以支持动态字段:
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.annotation.Id; import java.util.HashMap; @Document public class Product extends HashMap<String, Object> { @Id private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } }
- 调整控制器代码,将请求中
product节点的属性直接放入Product对象:
@PostMapping("/product") public void FeedConsume(@RequestBody Map<String, Object> requestBody, @RequestParam(value = "site_name") String siteName, @RequestParam(value = "site_key") String siteKey){ Map<String, Object> productAttrs = (Map<String, Object>) requestBody.get("product"); Product product = new Product(); product.putAll(productAttrs); productRepo.save(product); }
这种方式完全兼容任意数量的动态字段,不需要额外的序列化配置。
内容的提问来源于stack exchange,提问作者voila
相关产品推荐
相关产品推荐

