如何把 Java properties 转换为具有层级结构的字典

2021-08-24 09:47:13 +08:00
 MiketsuSmasher
java.class.version = 60.0
java.home = /usr/lib/jvm/java-16-openjdk
java.runtime.name = OpenJDK Runtime Environment
java.runtime.version = 16.0.2+7
java.specification.name = Java Platform API Specification
java.specification.vendor = Oracle Corporation
java.specification.version = 16
java.vendor = N/A
java.vendor.url = https://openjdk.java.net/
java.vendor.url = https://openjdk.java.net/
java.vendor.url.bug = https://bugreport.java.com/bugreport/
java.vendor.url.bug = https://bugreport.java.com/bugreport/
java.vendor.url.bug = https://bugreport.java.com/bugreport/
java.version = 16.0.2
java.version.date = 2021-07-20
java.vm.name = OpenJDK 64-Bit Server VM
java.vm.specification.name = Java Virtual Machine Specification
java.vm.specification.vendor = Oracle Corporation
java.vm.specification.version = 16
java.vm.vendor = Oracle Corporation
java.vm.version = 16.0.2+7
sun.arch.data.model = 64

我用 javaproperties 模块把上面内容转换成了字典:

{'java.class.version': '60.0',
 'java.home': '/usr/lib/jvm/java-16-openjdk',
 'java.runtime.name': 'OpenJDK Runtime Environment',
 'java.runtime.version': '16.0.2+7',
 'java.specification.name': 'Java Platform API Specification',
 'java.specification.vendor': 'Oracle Corporation',
 'java.specification.version': '16',
 'java.vendor': 'N/A',
 'java.vendor.url': 'https://openjdk.java.net/',
 'java.vendor.url.bug': 'https://bugreport.java.com/bugreport/',
 'java.version': '16.0.2',
 'java.version.date': '2021-07-20',
 'java.vm.name': 'OpenJDK 64-Bit Server VM',
 'java.vm.specification.name': 'Java Virtual Machine Specification',
 'java.vm.specification.vendor': 'Oracle Corporation',
 'java.vm.specification.version': '16',
 'java.vm.vendor': 'Oracle Corporation',
 'java.vm.version': '16.0.2+7',
 'sun.arch.data.model': '64'}

但是我想根据这些 properties 的键中相同的部分,把它转换成具有层级结构的字典,类似于:

{
    'java': {
        'class': {
            'version': 60.0
        },
        'home': '/usr/lib/jvm/java-16-openjdk',
        'runtime': {
            'name': 'OpenJDK Runtime Environment',
            'version': '16.0.2+7'
        },
        'specification': {
            'name': 'Java Platform API Specification',
            'vendor': 'Oracle Corporation',
            'verison': 16
        },
        ...: ...  # 省略剩余的内容
    },
    'sun': {
        'arch': {
            'data': {
                'model': 64
            }
        }
    }
}

有没有第三方库方便进行转换?或者如果自己造轮子,提供一个思路?

2550 次点击
所在节点    Python
27 条回复
wolfie
2021-08-24 09:58:11 +08:00
properties => yml => json 🐶🐶
Morii
2021-08-24 10:02:02 +08:00
google 搜索 properties to json 找到的

https://tools.fromdev.com/property-to-json-converter.html

如果你是就转化一次,那可以满足你的需求 如果是实时的 hutools 也能做
egfegdfr
2021-08-24 10:02:06 +08:00
自己造轮子的话,可以用 map 集合来实现、具体可以看下 spring 如何加载 yml 配置文件。
passerbytiny
2021-08-24 10:02:52 +08:00
你这到底是要 java 的还是 python 的。如果是 java 的,基本上不可能。
sadfQED2
2021-08-24 10:03:39 +08:00
按行解析,用=符号分割,右边是值,左边再按小数点分割,最后结果整理成你需要的结构,感觉没啥复杂的呀
passerbytiny
2021-08-24 10:03:51 +08:00
手机操作不便,没打完就给回复了。

在 Java 上,
misaka19000
2021-08-24 10:03:59 +08:00
自己写个轮子就行了啊,估计不超过 100 行
MiketsuSmasher
2021-08-24 10:05:39 +08:00
@Morii 这个工具转换的结果不完整,它把 sun.arch.data.model 给弄丢了
passerbytiny
2021-08-24 10:17:49 +08:00
Java 没有对应数据字典的数据结构,虽然可以用多级 Map 来对应这种层级结构,但是无泛型约束的多级 Map 是个超垃圾的数据封装方式。

在 Java 这边,这种多级结构,Java 上可用的数据结构方式,只能是逐级引用的类(通常会用上静态内部类)。但是这种模式通常只讲究正向——代码决定配置文件。

还有一种方式是将这种配置文件转换成树 Tree,可能 JDK 本身就支持这种转换,但感觉 Tree 这种数据结构也不好用。
wucao219101
2021-08-24 10:53:17 +08:00
```java

Properties properties = new Properties();
properties.load(new FileInputStream("/path/test.properties"));

PropertiesPropertySource propertySource = new PropertiesPropertySource("map", properties);
Iterable<ConfigurationPropertySource> propertySources = ConfigurationPropertySources.from(propertySource);

Binder binder = new Binder(propertySources);
Map map = binder.bind("", Map.class).orElse(null);
System.out.println(map);

```

输出:

{java={runtime={name=OpenJDK Runtime Environment, version=16.0.2+7}, vendor=N/A, specification={version=16, name=Java Platform API Specification, vendor=Oracle Corporation}, class={version=60.0}, vm={version=16.0.2+7, specification={version=16, name=Java Virtual Machine Specification, vendor=Oracle Corporation}, vendor=Oracle Corporation, name=OpenJDK 64-Bit Server VM}, home=/usr/lib/jvm/java-16-openjdk, version=16.0.2}, sun={arch={data={model=64}}}}

用的 Spring Boot 的 API:

import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.core.env.PropertiesPropertySource;
zifangsky
2021-08-24 10:59:46 +08:00
如果自己造轮子的话,可以考虑转成一棵通用树,再依次遍历输出
dongfangshangren
2021-08-24 11:03:10 +08:00
自己写个代码 一个递归就完了
hecz
2021-08-24 11:10:31 +08:00
yaml
wucao219101
2021-08-24 11:21:46 +08:00
micean
2021-08-24 11:37:25 +08:00
new HashLinkedMap()
readLine
split
map.putIfAbsent
json.prettyPrint

不就完事了
RRRoger
2021-08-24 11:37:30 +08:00
自己写代码就可以吧 挺简单的逻辑
GuuJiang
2021-08-24 12:24:40 +08:00
老老实实换成 yml 或者 json 配置吧
Properties 根本就不是为这种场景设计的,key 里的多级结构仅仅起到一个人肉命名空间的作用,实际使用时只能当作一个整体,换成个熟悉的例子,就好比 package 名字一样,有 com.example.x 和 com.example.y 存在,除非真的在 com.example 下面有类存在,否则 com.example 就不是一个正确的包名,不能理解为一个“parent package”,同理还有 redis 或者其他的 k-v 存储里,我们通常会在 key 名字里加上点分结构,为的是在人的逻辑上存在一个“树形”结构,但是对于存储来说根本就不关心这个点的存在,只认整体
而只有在 yml 这类配置里,本来就是为树形结构而生的,对树形结构有原生的支持,由于 yml 语法对 Properties 有一定的兼容性,你只需要把原本的 Properties 文件改为 yml,并且把=改为:就达到你想要的效果了
zhoudaiyu
2021-08-24 14:11:28 +08:00
@dongfangshangren #12
@RRRoger #16
@misaka19000 #7 我可能太菜了,用 python 写了 1 个小时都没写出来😂
xgfan
2021-08-24 15:10:07 +08:00
巧了么这不是,这沙雕需求我做过!!!当年大学帮老师写 xxx 管理系统的时候做过!

https://gist.github.com/XGFan/ccf4c0aeb3d9dc6e32ce4ccf6cdaf411
xgfan
2021-08-24 15:11:16 +08:00
但是,得指出来,这种做法是有大病的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/797618

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX