1.說明
jsonschema2pojo工具可以從JSON Schema(或示例JSON文件)生成Java類型,
並且可以配置生成Jackson 1.x,Jackson 2.x, Moshi 1.x或者Gson庫的注解。
支持將jsonschema2pojo作為Maven插件、Ant任務、命令行工具、
Gradle插件或嵌入到Java應用程序中。
本文僅介紹Maven插件使用方式。
另外該工具還提供了在線版本,
可以在網站上直接使用:jsonschema2pojo online
2.創建Maven工程
Eclipse -> File -> New -> Other... -> Maven -> Maven Project
創建一個簡單Maven工程,
pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>edu.yuwen.util</groupId>
<artifactId>json-file</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>generate-jsonschema2pojo</artifactId>
<description>jsonschema2pojo generates Java types from JSON Schema (or example JSON)</description>
</project>
3.引入Maven插件
Maven方式生成Java類需要jsonschema2pojo-maven-plugin,
在pom.xml引入這個插件:
<build>
<plugins>
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>1.0.2</version>
<configuration>
<sourceDirectory>${basedir}/src/main/resources/schema</sourceDirectory>
<targetPackage>com.example.types</targetPackage>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
里面的配置項指定了JSON schema文件的目錄,
以及生成的Java類的包路徑。
4.新建JSON Schema
在src/main/resources/schema目錄下
新建JSON Schema文件address.schema.json:
{
"$id": "https://example.com/address.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "An address similar to http://microformats.org/wiki/h-card",
"type": "object",
"properties": {
"post-office-box": {
"type": "string"
},
"extended-address": {
"type": "string"
},
"street-address": {
"type": "string"
},
"locality": {
"type": "string"
},
"region": {
"type": "string"
},
"postal-code": {
"type": "string"
},
"country-name": {
"type": "string"
}
},
"required": [ "locality", "region", "country-name" ],
"dependencies": {
"post-office-box": [ "street-address" ],
"extended-address": [ "street-address" ]
}
}
5.運行Maven插件
運行Maven命令,
執行插件功能:
mvn generate-sources
或者
mvn package
Maven執行成功后,
會生成target/generated-sources/jsonschema2pojo/com/example/types/Address.java類。
推薦使用mvn generate-sources,
這樣生成的target目錄更干凈些。
6.查看Address.java
package com.example.types;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
/**
* An address similar to http://microformats.org/wiki/h-card
*
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"post-office-box",
"extended-address",
"street-address",
"locality",
"region",
"postal-code",
"country-name"
})
public class AddressSchema {
@JsonProperty("post-office-box")
private String postOfficeBox;
@JsonProperty("extended-address")
private String extendedAddress;
@JsonProperty("street-address")
private String streetAddress;
/**
*
* (Required)
*
*/
@JsonProperty("locality")
private String locality;
/**
*
* (Required)
*
*/
@JsonProperty("region")
private String region;
@JsonProperty("postal-code")
private String postalCode;
/**
*
* (Required)
*
*/
@JsonProperty("country-name")
private String countryName;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("post-office-box")
public String getPostOfficeBox() {
return postOfficeBox;
}
@JsonProperty("post-office-box")
public void setPostOfficeBox(String postOfficeBox) {
this.postOfficeBox = postOfficeBox;
}
@JsonProperty("extended-address")
public String getExtendedAddress() {
return extendedAddress;
}
@JsonProperty("extended-address")
public void setExtendedAddress(String extendedAddress) {
this.extendedAddress = extendedAddress;
}
@JsonProperty("street-address")
public String getStreetAddress() {
return streetAddress;
}
@JsonProperty("street-address")
public void setStreetAddress(String streetAddress) {
this.streetAddress = streetAddress;
}
/**
*
* (Required)
*
*/
@JsonProperty("locality")
public String getLocality() {
return locality;
}
/**
*
* (Required)
*
*/
@JsonProperty("locality")
public void setLocality(String locality) {
this.locality = locality;
}
/**
*
* (Required)
*
*/
@JsonProperty("region")
public String getRegion() {
return region;
}
/**
*
* (Required)
*
*/
@JsonProperty("region")
public void setRegion(String region) {
this.region = region;
}
@JsonProperty("postal-code")
public String getPostalCode() {
return postalCode;
}
@JsonProperty("postal-code")
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
/**
*
* (Required)
*
*/
@JsonProperty("country-name")
public String getCountryName() {
return countryName;
}
/**
*
* (Required)
*
*/
@JsonProperty("country-name")
public void setCountryName(String countryName) {
this.countryName = countryName;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(AddressSchema.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("postOfficeBox");
sb.append('=');
sb.append(((this.postOfficeBox == null)?"<null>":this.postOfficeBox));
sb.append(',');
sb.append("extendedAddress");
sb.append('=');
sb.append(((this.extendedAddress == null)?"<null>":this.extendedAddress));
sb.append(',');
sb.append("streetAddress");
sb.append('=');
sb.append(((this.streetAddress == null)?"<null>":this.streetAddress));
sb.append(',');
sb.append("locality");
sb.append('=');
sb.append(((this.locality == null)?"<null>":this.locality));
sb.append(',');
sb.append("region");
sb.append('=');
sb.append(((this.region == null)?"<null>":this.region));
sb.append(',');
sb.append("postalCode");
sb.append('=');
sb.append(((this.postalCode == null)?"<null>":this.postalCode));
sb.append(',');
sb.append("countryName");
sb.append('=');
sb.append(((this.countryName == null)?"<null>":this.countryName));
sb.append(',');
sb.append("additionalProperties");
sb.append('=');
sb.append(((this.additionalProperties == null)?"<null>":this.additionalProperties));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
@Override
public int hashCode() {
int result = 1;
result = ((result* 31)+((this.postOfficeBox == null)? 0 :this.postOfficeBox.hashCode()));
result = ((result* 31)+((this.streetAddress == null)? 0 :this.streetAddress.hashCode()));
result = ((result* 31)+((this.postalCode == null)? 0 :this.postalCode.hashCode()));
result = ((result* 31)+((this.locality == null)? 0 :this.locality.hashCode()));
result = ((result* 31)+((this.countryName == null)? 0 :this.countryName.hashCode()));
result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode()));
result = ((result* 31)+((this.extendedAddress == null)? 0 :this.extendedAddress.hashCode()));
result = ((result* 31)+((this.region == null)? 0 :this.region.hashCode()));
return result;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof AddressSchema) == false) {
return false;
}
AddressSchema rhs = ((AddressSchema) other);
return (((((((((this.postOfficeBox == rhs.postOfficeBox)||((this.postOfficeBox!= null)&&this.postOfficeBox.equals(rhs.postOfficeBox)))&&((this.streetAddress == rhs.streetAddress)||((this.streetAddress!= null)&&this.streetAddress.equals(rhs.streetAddress))))&&((this.postalCode == rhs.postalCode)||((this.postalCode!= null)&&this.postalCode.equals(rhs.postalCode))))&&((this.locality == rhs.locality)||((this.locality!= null)&&this.locality.equals(rhs.locality))))&&((this.countryName == rhs.countryName)||((this.countryName!= null)&&this.countryName.equals(rhs.countryName))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.extendedAddress == rhs.extendedAddress)||((this.extendedAddress!= null)&&this.extendedAddress.equals(rhs.extendedAddress))))&&((this.region == rhs.region)||((this.region!= null)&&this.region.equals(rhs.region))));
}
}
7.引入插件依賴
當把Address.java放到工程的src/main/java目錄下時,
Java編譯會報錯,
這是因為生成的類型依賴於Commons Lang的equals、hashCode和toString。
一些模式結構也會以Jackson注釋的形式產生解析器提示。
需要在pom.xml中添加必要的依賴:
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.4</version>
</dependency>
</dependencies>
8.新建JSON文件
上面演示了從JSON Schema生成Java類,
下面演示從JSON文件生成Java類,
首先在src\main\resources\json目錄下,
新建一個JOSN文件person.json:
{
"name":"bob",
"age":33
}
9.修改插件配置
主要是指定了sourceType和sourceDirectory,
指定了源文件的格式是json和所在目錄。
<build>
<plugins>
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>1.0.2</version>
<configuration>
<sourceType>json</sourceType>
<sourceDirectory>${basedir}/src/main/resources/json</sourceDirectory>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<targetPackage>com.example.types</targetPackage>
<addCompileSourceRoot>true</addCompileSourceRoot>
<annotationStyle>jackson2</annotationStyle>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
10.生成Person.java類
mvn generate-sources執行成功后,
會生成src/main/java/com/example/types/Person.java:
package com.example.types;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"name",
"age"
})
public class Person {
@JsonProperty("name")
private String name;
@JsonProperty("age")
private Integer age;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("name")
public String getName() {
return name;
}
@JsonProperty("name")
public void setName(String name) {
this.name = name;
}
@JsonProperty("age")
public Integer getAge() {
return age;
}
@JsonProperty("age")
public void setAge(Integer age) {
this.age = age;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Person.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("name");
sb.append('=');
sb.append(((this.name == null)?"<null>":this.name));
sb.append(',');
sb.append("age");
sb.append('=');
sb.append(((this.age == null)?"<null>":this.age));
sb.append(',');
sb.append("additionalProperties");
sb.append('=');
sb.append(((this.additionalProperties == null)?"<null>":this.additionalProperties));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
@Override
public int hashCode() {
int result = 1;
result = ((result* 31)+((this.name == null)? 0 :this.name.hashCode()));
result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode()));
result = ((result* 31)+((this.age == null)? 0 :this.age.hashCode()));
return result;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Person) == false) {
return false;
}
Person rhs = ((Person) other);
return ((((this.name == rhs.name)||((this.name!= null)&&this.name.equals(rhs.name)))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.age == rhs.age)||((this.age!= null)&&this.age.equals(rhs.age))));
}
}
11.插件配置項說明
- sourceType:兩個可選值,JSON Schema或者JSON文件,默認為JSON Schema。
- sourceDirectory:源文件所在的目錄,會將該目錄下所有文件進行轉換,不支持指定單個文件,如果不想全部轉換,可以添加一個excludes節點。
- outputDirectory:生成Java Pojo類的(根)目錄,生成Java類的目錄為此目錄+包目錄,默認值為target/generated-sources/jsonschema2pojo。
- targetPackage:生成的Java pojo類的包路徑。
- addCompileSourceRoot:是否將輸出目錄作為項目的源碼根目錄。
- annotationStyle:生成的(字段)注解樣式,五個可選值:jackson1、jackson2、gson、moshi1和none,默認是jackson2,如果fastjson等工具不支持的,需要設置為none。
更多配置項的使用請參考:jsonschema2pojo-maven-plugin Optional Parameters
12.參考文章
使用maven根據JSON文件自動生成Java POJO類(Java Bean)源文件jsonschema2pojo github