我最近为一个返回的客户端启动了一个新的Java项目。我的首要任务之一是实现一个新功能,目标是使用JSON属性文件使应用程序全局可配置。
我发现最终的解决方案相对方便,所以我想我会在新的博客文章中分享它。此外,由于到目前为止我还没有写过任何Java博客文章,我发现它非常具有挑战性和趣味性。
介绍
在本文中,我们将:
- 创建一个新项目。
- 读取JSON文件和属性。
- 创建一个枚举。
- 将属性映射到通用枚举。
注意:如果您已经有一个项目,那么显然可以跳过目标是创建项目的第一章。同样,如果您不想使用Maven,也可以跳过它,并按照您的设置要求包含我们将要使用的库。
创建一个新项目
首先,我们将使用Maven入门套件创建一个新项目。为此,请在终端中运行以下命令:
$ 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
阅读JSON文件和属性
起初,我实施了一个快速的自定义解决方案,但我根本不满意结果。这就是为什么我试图在网上找到一个随时可用的解决方案,并找到了令人难以置信的开源库com.typesafe.config。
它利用了读取JSON文件和访问其属性的所有工作,没有依赖性,甚至与Java 8兼容。
至少这一次,谷歌搜索解决方案是一个很好的主意。
要使用该库,让我们将这个库的新依赖项添加到我们的pom.xml:
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
<version>1.3.4</version>
</dependency>
此外,我们还应该为我们添加以下内容<resources/>和<plugins/>目标,<build/>以便能够加载JSON文件(我们即将创建)并打包我们刚刚在JAR文件中引用的依赖项。
<resources>
<resource>
<directory>src/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
我们的构建终于成立了。我们现在可以继续下一步并创建我们的JSON属性文件。
默认情况下,配置库将尝试加载名为application.jsonsource 的文件作为属性。
因此,让我们保持简单并使用该预定义名称在新文件夹中创建src/resources/具有以下JSON内容的新文件:
{
"swiss": {
"cheese": "gruyere"
}
}
一切都准备好了。
我们可以将我们的应用程序(App.java在文件夹中src/main/java/com/jsontoenum/app)修改为init并从JSON文件加载属性并打印出我们喜欢的奶酪类型的名称。
package com.jsontoenum.app;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class App {
public static void main(String[] args) {
// Load and init the configuration library
final Config conf = ConfigFactory.load();
// Get the value of the JSON property
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 🧀
创建一个枚举
即使能够读取JSON属性已经很酷了,我很快意识到,在开发我的指定功能时,能够将属性映射到枚举将是强制性的,如果应用程序应该相应地表现不同。
此外,瑞士生产不止一种奶酪。
因此,作为我们的下一步,我们可以在文件夹中创建一个枚举src/main/java/com/jsontoenum/app/,可以列出来自该国法语区的几个奶酪:
package com.jsontoenum.app;
public enum Cheese {
GRUYERE,
TETE_DE_MOINE,
CHAUX_DABEL,
RACLETTE,
VACHERIN,
TOMME
}
将属性映射到通用枚举
在本文中,我们使用奶酪进行演示,但很明显,瑞士出口许多其他产品,如巧克力和手表。
同样,我正在处理的应用程序不仅包含单个枚举。这就是为什么我们不仅要添加一个方法来将属性解析为单一类型的枚举,而是在我们的application(App.java)中将其声明为泛型。
private static <E extends Enum<E>> E getEnumProperty(final Config conf, final String key, final Class<E> myClass) {
// If no config loaded
if (conf == null) {
return null;
}
// If the config doesn't contains the key
if (!conf.hasPath(key)) {
return null;
}
// As previously, load the key value
final String keyValue = conf.getString(key);
// Does the property has a value
if (keyValue == null || keyValue.isEmpty()) {
return null;
}
// Map the property to the ENUM
return Enum.valueOf(myClass, keyValue.toUpperCase());
}
最后,对于最后的测试,让我们main通过加载枚举并测试它来增强我们的方法,以显示奶酪是否是我们最喜欢的奶酪:
public static void main(String[] args) {
// Load and init the configuration library
final Config conf = ConfigFactory.load();
// Get the value of the JSON property
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));
}
}
Voilà,就是这样,仅此而已。
您可以尝试使用上一个命令行运行我们的项目,如果一切按计划进行,输出应如下所示:
[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 🧀
樱桃蛋糕🍒🎂
如果您想避免创建自己的项目和复制上述代码的麻烦,我已经在线发布了该项目,成为我的客人。
$ git clone https://github.com/peterpeterparker/json-to-enum.git
翻译自:https://medium.com/better-programming/map-a-json-file-to-enum-in-java-d399bac0759d












网友评论