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
}
}
}
}
有没有第三方库方便进行转换?或者如果自己造轮子,提供一个思路?
暂时把问题解决了,使用了技术含量极高的手动转换,反正就那么一个properties需要转换
1
wolfie 2021-08-24 09:58:11 +08:00
properties => yml => json 🐶🐶
|
2
28Sv0ngQfIE7Yloe 2021-08-24 10:02:02 +08:00
google 搜索 properties to json 找到的
https://tools.fromdev.com/property-to-json-converter.html 如果你是就转化一次,那可以满足你的需求 如果是实时的 hutools 也能做 |
3
egfegdfr 2021-08-24 10:02:06 +08:00
自己造轮子的话,可以用 map 集合来实现、具体可以看下 spring 如何加载 yml 配置文件。
|
4
passerbytiny 2021-08-24 10:02:52 +08:00 via Android
你这到底是要 java 的还是 python 的。如果是 java 的,基本上不可能。
|
5
sadfQED2 2021-08-24 10:03:39 +08:00 via Android
按行解析,用=符号分割,右边是值,左边再按小数点分割,最后结果整理成你需要的结构,感觉没啥复杂的呀
|
6
passerbytiny 2021-08-24 10:03:51 +08:00 via Android
手机操作不便,没打完就给回复了。
在 Java 上, |
7
misaka19000 2021-08-24 10:03:59 +08:00
自己写个轮子就行了啊,估计不超过 100 行
|
8
MiketsuSmasher OP @Morii 这个工具转换的结果不完整,它把 sun.arch.data.model 给弄丢了
|
9
passerbytiny 2021-08-24 10:17:49 +08:00 via Android
Java 没有对应数据字典的数据结构,虽然可以用多级 Map 来对应这种层级结构,但是无泛型约束的多级 Map 是个超垃圾的数据封装方式。
在 Java 这边,这种多级结构,Java 上可用的数据结构方式,只能是逐级引用的类(通常会用上静态内部类)。但是这种模式通常只讲究正向——代码决定配置文件。 还有一种方式是将这种配置文件转换成树 Tree,可能 JDK 本身就支持这种转换,但感觉 Tree 这种数据结构也不好用。 |
10
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; |
11
zifangsky 2021-08-24 10:59:46 +08:00
如果自己造轮子的话,可以考虑转成一棵通用树,再依次遍历输出
|
12
dongfangshangren 2021-08-24 11:03:10 +08:00 via iPhone
自己写个代码 一个递归就完了
|
13
hecz 2021-08-24 11:10:31 +08:00
yaml
|
14
wucao219101 2021-08-24 11:21:46 +08:00
|
15
micean 2021-08-24 11:37:25 +08:00
new HashLinkedMap()
readLine split map.putIfAbsent json.prettyPrint 不就完事了 |
16
RRRoger 2021-08-24 11:37:30 +08:00
自己写代码就可以吧 挺简单的逻辑
|
17
GuuJiang 2021-08-24 12:24:40 +08:00 via iPhone 2
老老实实换成 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,并且把=改为:就达到你想要的效果了 |
18
zhoudaiyu 2021-08-24 14:11:28 +08:00
|
19
6IbA2bj5ip3tK49j 2021-08-24 15:10:07 +08:00
巧了么这不是,这沙雕需求我做过!!!当年大学帮老师写 xxx 管理系统的时候做过!
https://gist.github.com/XGFan/ccf4c0aeb3d9dc6e32ce4ccf6cdaf411 |
20
6IbA2bj5ip3tK49j 2021-08-24 15:11:16 +08:00
但是,得指出来,这种做法是有大病的。
|
21
O5oz6z3 2021-08-24 18:53:13 +08:00
有点麻烦,`java.vendor = N/A` 有子节点,`java.vendor.url = ……/openjdk.java.net/` 有复数行。
如果不考虑那么多,贡献一个 py 大致思路,不保证对:用 configparser 读取 ini 格式的数据变成字典(有个参数允许同键名的复数行),遍历字典(for key, value in dict.items()),将键名按点分割(key.split(".")),遍历分割后键名的每个层级,用 dict.setdefault(parentkey, dict())初始化每个层级,最后赋值。 最近在哪见过类似的格式,不过想不起来了。 |
22
MiketsuSmasher OP @O5oz6z3 可以通过转换 java.vendor 为{'java': 'vendor': {'': 'N/A', 'url': ...}解决。
至于重复行的问题,反正都是一样的,保留一行就好了。 |
23
xuanbg 2021-08-24 20:23:43 +08:00
对象序列化成 json,json 再反序列化成 map 就好了。
|
24
O5oz6z3 2021-08-24 21:30:50 +08:00
@MiketsuSmasher #22 好主意,我看到过 setuptools 也是用这种写法
|
25
zhoudaiyu 2021-08-25 13:13:24 +08:00
Python 简单搞了一下,不支持这种不满足 json 定义的格式的,比如'java.vendor.url': 'https://openjdk.java.net/' 和 'java.vendor.url.bug': 'https://bugreport.java.com/bugreport/'
```py import re import json ori = """{'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.url.bug.b': 'https://bugreport.java.com/bugreport/', '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'}""" prop_regex = re.compile("'(?P<key>.*)':\s*'(?P<value>.*)'\s*") def dict_filter(dic: dict, _str: str) -> dict: ret_dict = dict() for k in dic.keys(): if k != _str: ret_dict[k] = dic[k] return ret_dict def get_deepest_dict(dic: dict, keys: list) -> dict: _dic = dict() _dic = dic for i in keys: _dic = _dic[i] return _dic def prop2json_converter(src_str: str) -> str: """ Convert property string to json string. :param src_str: source property string :return: a wrapped json string """ try: _dict = dict() ret_dict = dict() for ln in src_str.split("\n"): matched_k_v = prop_regex.search(ln) if matched_k_v: _dict[matched_k_v.groupdict().get("key")] = matched_k_v.groupdict().get("value") for k, v in _dict.items(): for cnt, kk in enumerate(k.split(".")): _l = k.split(".")[:cnt] if cnt != len(k.split(".")) - 1: if not _l: ret_dict.setdefault(kk, dict()) else: _r = get_deepest_dict(ret_dict, _l) _r.setdefault(kk, dict()) else: if not _l: ret_dict.setdefault(kk, v) else: _r = get_deepest_dict(ret_dict, _l) _r[kk] = v except (TypeError, AttributeError): return json.dumps({"data": None, "err": "Invalid input string"}, ensure_ascii=False, indent=4) return json.dumps({"data": ret_dict, "err": ""}, ensure_ascii=False, indent=4) if __name__ == '__main__': print(prop2json_converter(ori)) |
26
zhoudaiyu 2021-08-25 13:17:32 +08:00
@zhoudaiyu #25 为啥不支持 markdown....换下 gist....https://gist.github.com/BiTree/f21adc0e6ce67c18784690dfbaf15af8
|