2024 Clojure 状态调查!分享您的想法。

欢迎!请查阅关于页面以了解更多关于如何使用本网站的信息。

0
Clojure

描述

大家好!我正在解析一个 Spring Boot 配置文件。值并不重要

server.port: 8000
spring.application.name: some application
spring.datasource.driver-class-name: org.whatever.Driver
spring.datasource.password: some_password
spring.datasource.platform: postgres
spring.datasource.url: jdbc:postgresql:does_not_matter
spring.datasource.username: some_username
spring.jpa.database: POSTGRESQL
some.service.endpoint: http://whatever
some.other.service.endpoint: http://something_else

我想提取/分组该文件的不同部分,并寻找进行这种操作的建议/惯用法。我正在尝试遵循 "数据 > 函数 > 宏" 的惯用法和 "一个数据结构的一百个更好的函数"。

具体来说,我想解析/分组网络端点,然后是数据库属性,以便使用一些业务逻辑进行验证。

我已经使用 java.util.Properties 解析了该文件,所以在这里_interesting_。上面的文件已转换为映射。

解决方案 1

为每个我想要的“分组”创建一个单独的函数,解析我想要的,并返回一个只包含我想要的数据的新映射。

  • defn get-endpoints [props] 返回

`

{
    "some.service.endpoint" "http://whatever",
    "some.other.service.endpoint" "http://something_else"
}

`

  • defn get-database-properties [props] 等等。

解决方案 2

向原始映射中添加额外的键来分组我想要的内容。

defn parse-groupings [props] 返回

    {
        "server.port" "8000",
        "spring.application.name" "some application",
        "spring.datasource.driver-class-name" "org.whatever.Driver",
        ;; the rest of the original properties
       :groupings {
            :web-endpoints {
               ;; web endpoints go here
           },
           :database-props {
             ;; database properties get embedded here
           }

    }

解决方案 ???

当然,还有更多解决方案,但我想知道社区有何推荐。

谢谢!

1 答案

0

你可以这样做一个简单的

(doto (Properties.)
  (.load (io/reader "props.properties")))

将得到一个映射,如

{...
  "server.port" "8080"
 ...}

可以按字符串访问值 (get props-map "server.port")

我更喜欢这种方法,因为它更易于使用 git grep 检索值。

对于更“惯用”的解决方案,你可以这样做:

(defn parse-props
  [in & {:keys [handlers default-handler]
         :or   {default-handler identity}}]
  (into {}
    (map (fn [[k v]]
           (let [[kw-name & ns-parts] (reverse (string/split k #"\."))
                 kw (keyword (string/join "." ns-parts)
                      kw-name)
                 f (get handlers kw default-handler)]
             [kw (f v)])))
    (doto (Properties.)
      (.load (io/reader in)))))
(parse-props "props.properties"
  :handlers {:server/port #(Long/parseLong %)})

将得到一个映射,如

{....
 :server/port 8080
 ...}
作者:
感谢,@Enzzo,但我更想知道有关分组地图的建议,比如OP中的`get-endpoints`。
作者:
现在重新阅读问题,我发现它更关于一个选择数据的函数,而不是与props相关的内容。抱歉给出错误的回答。

关于“get-endpoints”,从代码角度来看,我会写这样的东西(defn find-endpoints [config] (into {} (filter #(string/ends-with? % ".endpoint")) config))。
如果需要的话,我们可以将其关联回config映射中。
我认为在此函数的“设计”上花费太多时间是没有必要的。这是一个简单的函数,可能会在不到10个地方被调用。它可能不会随着时间的推移而改变。

从配置的角度来看,我会创建一个明确的app.config.endpoint-props=..service1.endpoint,...service2.endpoint,以避免命名约定。
...