Spring Boot中如何实现指定嵌套结构的JSON数据映射?
Spring Boot 多层嵌套JSON映射实现方案
Spring Boot默认集成的Jackson组件可直接完成该结构的JSON序列化/反序列化,无需额外引入第三方依赖,按JSON层级定义对应Java实体类即可。
1. 按层级定义映射实体
所有实体必须提供无参构造方法,否则JSON解析框架无法实例化对象会直接报错。若项目引入Lombok,可给类加@Data注解省略getter/setter/无参构造的冗余代码。
最外层实体 Document.java
import java.util.List; public class Document { private String type; private Counterparty counterparty; private List<Nomenclature> nomenclatures; public Document() {} // 字段getter、setter public String getType() { return type; } public void setType(String type) { this.type = type; } public Counterparty getCounterparty() { return counterparty; } public void setCounterparty(Counterparty counterparty) { this.counterparty = counterparty; } public List<Nomenclature> getNomenclatures() { return nomenclatures; } public void setNomenclatures(List<Nomenclature> nomenclatures) { this.nomenclatures = nomenclatures; } }
交易方信息实体 Counterparty.java
public class Counterparty { private String name; private String inn; private String kpp; public Counterparty() {} // 字段getter、setter public String getName() { return name; } public void setName(String name) { this.name = name; } public String getInn() { return inn; } public void setInn(String inn) { this.inn = inn; } public String getKpp() { return kpp; } public void setKpp(String kpp) { this.kpp = kpp; } }
品目信息实体 Nomenclature.java
cod字段是对象数组,需要定义对应子项实体,可写为静态内部类或单独顶级类:
import java.util.List; public class Nomenclature { private List<CodItem> cod; private String name; private String article; public Nomenclature() {} // cod子项实体 public static class CodItem { private String type; private String val; public CodItem() {} // 字段getter、setter public String getType() { return type; } public void setType(String type) { this.type = type; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } } // Nomenclature自身字段getter、setter public List<CodItem> getCod() { return cod; } public void setCod(List<CodItem> cod) { this.cod = cod; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArticle() { return article; } public void setArticle(String article) { this.article = article; } }
注:示例JSON中
kpp为空字符串,可正常映射为String类型空值,不需要额外配置。
2. 业务代码中使用
接口层直接接收参数
在Controller层通过@RequestBody注解即可直接拿到映射完成的对象:
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class DocumentController { @PostMapping("/document/parse") public String parseDocument(@RequestBody Document document) { // 直接操作映射完成的对象即可 String docType = document.getType(); String counterpartyInn = document.getCounterparty().getInn(); for (Nomenclature nom : document.getNomenclatures()) { String goodsName = nom.getName(); for (Nomenclature.CodItem cod : nom.getCod()) { String codValue = cod.getVal(); } } return "parse success"; } }
手动解析JSON字符串
如果是工具类场景手动解析,直接调用Jackson的ObjectMapper即可:
import com.fasterxml.jackson.databind.ObjectMapper; public class JsonParseTest { public static void main(String[] args) throws Exception { String jsonStr = "待解析的JSON字符串内容"; ObjectMapper objectMapper = new ObjectMapper(); Document document = objectMapper.readValue(jsonStr, Document.class); } }
3. 常见映射失败排查点
- 字段名不匹配:如果Java字段名和JSON键名不一致,在字段上添加
@com.fasterxml.jackson.annotation.JsonProperty("JSON对应键名")注解指定映射关系 - 空字符串转数值类型报错:如果后续有数值类型字段传空值,可配置全局Jackson宽松反序列化模式,或在对应字段加
@JsonFormat(lenient = com.fasterxml.jackson.annotation.OptBoolean.TRUE) - 内部类实例化失败:如果
CodItem定义为Nomenclature的内部类,必须加static修饰,否则框架无法调用无参构造 - 字段访问权限问题:不要将实体类字段设为
private且不提供getter/setter,框架无法访问私有字段会导致映射值为null
内容的提问来源于stack exchange,提问作者tvisteljas
相关产品推荐
相关产品推荐

