You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含嵌套对象的YAML映射为Java POJO并实现配置读取

问题场景与解决方案

一、实体类代码定义

// Product类
public class Product {
    private String name;
    private Long id;

    // 需添加构造方法、getter和setter
}

// Departament类
public class Departament {
    private String name;
    private Product product;

    // 需添加构造方法、getter和setter
}

二、无法正常工作的YAML示例

这份YAML逻辑看似合理,但Spring的@ConfigurationProperties无法自动将部门配置中的产品名称转换为对应的Product对象,加载时会报错:

products:
  - name: "Laptop"
    id: 1
  - name: "Phone"
    id: 2

departaments:
  - name: "Tech"
    product: "Laptop"  # 直接写产品名称,Spring无法自动转为Product实例
  - name: "Electronics"
    product: "Phone"

三、问题原因

Spring默认的配置属性绑定仅支持基础类型、简单嵌套对象的转换,无法自动根据字符串名称匹配已定义的Product对象,必须手动添加关联逻辑。

四、解决办法

方式一:配置类内手动关联

先加载所有产品与部门数据,再在配置类中完成对象匹配:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Configuration
@ConfigurationProperties(prefix = "")
public class AppConfig {
    private List<Product> products;
    private List<Departament> departaments;

    // 属性加载完成后自动执行关联逻辑
    @PostConstruct
    public void linkProductsToDepartments() {
        // 将产品转为「名称-对象」映射,方便快速查找
        Map<String, Product> productMap = products.stream()
                .collect(Collectors.toMap(Product::getName, product -> product));
        
        // 为每个部门匹配对应Product对象
        departaments.forEach(dept -> {
            String productName = (String) dept.getProduct();
            dept.setProduct(productMap.get(productName));
        });
    }

    // 必须添加getter、setter,Spring才能完成属性绑定
    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }

    public List<Departament> getDepartaments() {
        return departaments;
    }

    public void setDepartaments(List<Departament> departaments) {
        this.departaments = departaments;
    }
}

方式二:自定义类型转换器

编写转换器,让Spring知晓如何将字符串转换为Product对象:

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class StringToProductConverter implements Converter<String, Product> {
    private final Map<String, Product> productMap;

    // 构造注入所有产品,提前转为映射表
    public StringToProductConverter(List<Product> products) {
        this.productMap = products.stream()
                .collect(Collectors.toMap(Product::getName, p -> p));
    }

    @Override
    public Product convert(String productName) {
        return productMap.get(productName);
    }
}

然后在Departament的product字段上添加转换注解:

import org.springframework.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class StringToProductConverter implements Converter<String, Product> {
    private final Map<String, Product> productMap;

    // 构造注入所有产品,提前转为映射表
    public StringToProductConverter(List<Product> products) {
        this.productMap = products.stream()
                .collect(Collectors.toMap(Product::getName, p -> p));
    }

    @Override
    public Product convert(String productName) {
        return productMap.get(productName);
    }
}

这种方式下原YAML无需修改,Spring会自动通过转换器完成名称到对象的映射。

五、验证

启动Spring应用后,注入AppConfig即可获取已关联对应Product对象的Departament列表。

内容的提问来源于stack exchange,提问作者roberto fernandez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:02:21