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

PKL集成Hocon配置:自定义资源读取器如何返回复合结构?

问题

我的项目当前使用Hocon配置,计划逐步迁移至PKL配置框架。为保障过渡阶段顺畅,我希望能在PKL中引用旧配置中的部分值。我尝试通过实现自定义资源读取器来实现该需求,代码如下:

import com.typesafe.config.*;
import org.pkl.core.SecurityManagerException;
import org.pkl.core.resource.ResourceReader;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Optional;

class HoconResourceReader implements ResourceReader {
    private Config config = ConfigFactory.load();
    public Optional<Object> read(URI uri) {
        if (config.hasPath(uri.getSchemeSpecificPart())) {
            var value = config.getAnyRef(uri.getSchemeSpecificPart());
            return Optional.of(value.toString());
        } else {
            return Optional.empty();
        }
    }
    public String getUriScheme() { return "hocon"; }
    public boolean hasHierarchicalUris() { return true; }
    public boolean isGlobbable() { return true; }
}

该读取器可正常处理字符串等标量值,但我需要它支持返回带属性的动态对象这类复合结构。请问是否有办法从自定义值创建此类对象?

回答

要让自定义资源读取器返回PKL的动态对象(适配Hocon复合结构),不能直接返回字符串,需要将Hocon的复合结构递归转换成PKL兼容的DynamicObject实例,具体实现如下:

  1. 核心思路
    利用Hocon的ConfigValue遍历所有类型的配置节点,递归转换为PKL支持的类型:

    • 标量值(字符串、数字、布尔、null)直接返回原始Java类型,PKL会自动适配
    • Hocon对象(ConfigObject)通过PKL的DynamicObjects.createObjectBuilder()构建动态对象,逐个添加转换后的属性
    • Hocon列表(ConfigList)转换为Java列表,内部元素递归转换
  2. 修改后的完整代码

import com.typesafe.config.*;
import org.pkl.core.resource.ResourceReader;
import org.pkl.core.util.DynamicObjects;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

class HoconResourceReader implements ResourceReader {
    private final Config config = ConfigFactory.load();

    @Override
    public Optional<Object> read(URI uri) {
        String path = uri.getSchemeSpecificPart();
        if (!config.hasPath(path)) {
            return Optional.empty();
        }
        ConfigValue value = config.getValue(path);
        return Optional.of(convertHoconValueToPkl(value));
    }

    private Object convertHoconValueToPkl(ConfigValue hoconValue) {
        ConfigValueType type = hoconValue.valueType();
        return switch (type) {
            case OBJECT -> {
                ConfigObject configObject = (ConfigObject) hoconValue;
                var builder = DynamicObjects.createObjectBuilder();
                configObject.forEach((key, val) ->
                    builder.put(key, convertHoconValueToPkl(val))
                );
                yield builder.build();
            }
            case LIST -> {
                ConfigList configList = (ConfigList) hoconValue;
                List<Object> pklList = new ArrayList<>();
                for (ConfigValue item : configList) {
                    pklList.add(convertHoconValueToPkl(item));
                }
                yield pklList;
            }
            case STRING, NUMBER, BOOLEAN -> hoconValue.unwrapped();
            case NULL -> null;
        };
    }

    @Override
    public String getUriScheme() {
        return "hocon";
    }

    @Override
    public boolean hasHierarchicalUris() {
        return true;
    }

    @Override
    public boolean isGlobbable() {
        return true;
    }
}
  1. PKL中的使用示例
    现在可以直接在PKL配置中引用Hocon的复合结构,比如:
import "hocon:app.database" as dbConfig

database {
  url = dbConfig.url
  credentials {
    username = dbConfig.credentials.username
    password = dbConfig.credentials.password
  }
}

这样修改后,读取器就能正确解析Hocon中的嵌套对象和列表,让你在PKL中直接访问嵌套属性,满足过渡阶段的配置复用需求。

内容的提问来源于stack exchange,提问作者Artem Petrov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:02:35