(给ImportNew加星标,提高Java技能)

编译:ImportNew/唐尤华

medium.com/better-programming/map-a-json-file-to-enum-in-java-d399bac0759d

本文以瑞士奶酪为例介绍了如何从头把 JSON 文件映射成 Java 枚举。

最近为一个回头客新做了一个 Java 项目。第一个任务用 JSON 属性文件实现程序全局配置。

功能完成之后发现这个解决方案用起来很方便,打算写一篇博客分享。由于之前没有写过任何 Java 技术博客,发现这个过程相当挑战而且趣味。

0. 引言

本文涵盖以下内容:

  1. 创建新项目
  2. 读取 JSON 文件和属性
  3. 创建枚举
  4. 把属性映射为泛型枚举

注意: 如果你已经有了一个项目,可以跳过接下来的第一章。同样,如果不使用 Maven 也可以跳过,按照自己的设置添加要使用的开发库。

1. 创建新项目

首先,用 Maven starter 工具新建项目。在终端中运行以下命令:

$ mvn archetype:generate -DgroupId=com.jsontoenum.app -DartifactId=json-to-enum -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

如果一切顺利,跳转到下面目录应该能够成功编译:

$ cd json-to-enum/ && mvn package

2. 读取 JSON 文件和属性

起初,我自己实现了一个快速解决方案,但是对结果一点也不满意。这就是为什么试着在网上寻找一个现成的解决方案,结果发现了神奇的 com.typesafe.config 开源三方库。

它提供了读取 JSON 文件和访问属性需要的所有功能,没有依赖而且兼容 Java 8。

至少这一次,用谷歌搜索是一个绝妙的主意。

使用前,需要在到pom.xml 中增加依赖:

com.typesafeconfig1.3.4

此外,还要把下列 和 信息添加到中,以便顺利加载(即将创建的) JSON 文件并把刚才 JAR 文件中引用的依赖项打包。

src/resources
org.apache.maven.pluginsmaven-shade-plugin3.2.0packageshade

build 配置完毕,现在可以进入下一步,创建 JSON 属性文件。

默认情况下,configuration 开发库会把名为 application.json的文件作为属性源文件加载。

简单起见,在新文件夹 src/resources/ 中用默认文件名创建配置,包含以下 JSON 内容:

{
"swiss": {
"cheese": "gruyere"
  }
}

一切设置妥当,开始编码。

修改程序,在src/main/java/com/jsontoenum/app 文件夹中的App.java 中初始化并从 JSON 文件加载属性,然后输出我们喜爱的 cheese名称。

package com.jsontoenum.app;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class App {
public static void main(String[] args) {
// 加载并初始化 configuration 开发库
      final Config conf = ConfigFactory.load();
// 读取 JSON 属性值
      final String cheese = conf.getString("swiss.cheese");
      System.out.println(String.format("I like %s ?", cheese));
   }
}

在终端中执行下列命令,全部编译并运行程序:

$ mvn package && java -cp target/json-to-enum-1.0-SNAPSHOT.jar com.jsontoenum.app.App

如果一切正常,在控制台输出的末尾应显示下列内容:

[INFO] -------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------
[INFO] Total time:  2.179 s
[INFO] Finished at: 2019-08-16T15:04:35+02:00
[INFO] -------------------------------------------------------------
I like gruyere

3. 创建枚举

尽管能够读取 JSON 属性已经很酷了,但我很快意识到,由于应用程序的行为各有不同,在开发新功能时必须把属性映射为枚举。

而且,瑞士产的奶酪不止一种。

因此,下一步可以在文件夹 src/main/java/com/jsontoenum/app/ 中创建一个枚举,可以列出产自讲法语国家的奶酪:

package com.jsontoenum.app;
public enum Cheese {
   GRUYERE,
   TETE_DE_MOINE,
   CHAUX_DABEL,
   RACLETTE,
   VACHERIN,
   TOMME
}

4. 把属性映射到泛型枚举

本文使用奶酪只是为了演示。很明显,瑞士还出口许多其他产品,比如巧克力和手表。

同样,正在开发的应用程序不只包含一个枚举。这就是为什么不仅要专门添加一个方法来解析单个枚举类型的属性,还要在 App.java 中声明为泛型。

private static > E getEnumProperty(final Config conf, final String key, final Class myClass) {// 如果 config 未加载if (conf == null) {return null;
    }// 如果 config 不包含 keyif (!conf.hasPath(key)) {return null;
    }// 和之前一样,加载 key 值
    final String keyValue = conf.getString(key);// 判断属性值存在if (keyValue == null || keyValue.isEmpty()) {return null;
    }// 把属性值映射为枚举return Enum.valueOf(myClass, keyValue.toUpperCase());
}

最后的测试,可以改进main方法加载枚举,测试结果是否是我们喜欢的奶酪:

public static void main(String[] args) {
// 加载并初始化 configuration 开发库
   final Config conf = ConfigFactory.load();
// 获取 JSON 属性值
   final Cheese cheese =
                getEnumProperty(conf, "swiss.cheese", Cheese.class);
if (Cheese.GRUYERE.equals(cheese)) {
       System.out.println(String.format("I really like %s ?", cheese));
   } else {
       System.out.println(String.format("%s is ok", cheese));
   }
}

以上是所有内容。

用之前的命令行运行,如果一切按计划进行,输出结果如下:

[INFO] -------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------
[INFO] Total time:  2.437 s
[INFO] Finished at: 2019-08-16T15:43:42+02:00
[INFO] -------------------------------------------------------------
I really like GRUYERE

5. 精华

如果想要省去新建项目和复制代码的麻烦,我已经在网上发布了这个项目,请随意。

$ git clone https://github.com/peterpeterparker/json-to-enum.git