天天看點

使用 Json Schema 定義 API

本文位址:使用 Json Schema 定義 API

前面我們介紹了

Json Schema

的基本内容,這篇文章我們結合

jsonschema2pojo

工具深入分析如何使用

Json Schema

生成 API,學習更多關于

Json Schema

的關鍵字等知識。

jsonschema2pojo

該庫提供了多種使用

Json Schame

檔案生成 Java 類的方法,比如

Maven

插件,

Gradle

Ant

任務, 以及直接使用指令行,甚至還可以在代碼中直接使用,具體參照 jsonschema2pojo Getting Started

這裡我直接采用 Mac 指令行的方式,在 Mac 下安裝此指令的方式比較簡單,直接運作

brew install jsonschema2pojo

安裝即可。

properties

在一個類中,最關鍵的就是屬性了,每個類都可能有多個屬性,在

Json Schema

中就是通過

properties

來定義類的屬性的, properties 中的每個條目都是所定義類的一個屬性。

比如,對于此 Json Schema

MyObject.json

{
    "type" : "object",
    "properties" : {
        "foo" : {
            "type" : "string"
        }
    }
}
           

我們執行

jsonschema2pojo

任務後,可以生成對應的 Java 類:

public class MyObject {
    private String foo;
    public String getFoo() {
       return foo;
    }
    public void setFoo(String foo) {
       this.foo = foo;
    }
}
           

type

像我們 Java 中有多種類型,那不同的類型在 Json Schema 中如何表示呢?一般通用的轉換如下所示,這也是 jsonschema2pojo 工具預設使用的轉換方式:

Schema Type | Java Type

:-: | :-:

string | java.lang.String

number | java.lang.Double

integer| java.lang.Integer

boolean| java.lang.Boolean

object | 自己生成的類

array | java.util.List

array(with “uniqueItems”:true)|java.util.Set

null | java.lang.object

any | java.lang.object

值的注意的是,如果我們增加了

usePrimitives

選項,對于

Integer, Double, Boolean

這三個包裝類将會轉換成基本類型

int, double, boolean

additionalProperties

我們平時開發中,為了類利于擴充,有時會給類增加一個

Map

類型的屬性,這樣當外部需要傳更多的參數給我們時,不需要更改API,直接将參數放到這個

Map

裡就可以快速實作。

jsonschema2pojo

同樣也實作了這個功能,當我們沒有指定

additionalProperties

屬性為

false

或者沒有指定

additionalProperties

屬性時,

jsonschema2pojo

會為我們定義的類自動生成一個類型為

Map

additionalProperties

屬性。

比如:

{
    "type" : "object"
}
           

或者

{
    "type" : "object",
    "additionalProperties" : {}
}
           

生成的類:

public class MyObject {
    private java.util.Map<String, Object> additionalProperties = new java.util.HashMap<String, Object>();

    @org.codehaus.jackson.annotate.JsonAnyGetter
    public java.util.Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @org.codehaus.jackson.annotate.JsonAnySetter
    public void setAdditionalProperties(String name, Object value) {
        this.additionalProperties.put(name, value);
    }
}
           

items

items

用于指定我們定義

List

以及

Set

類型時的子元素詳情,比如子元素的類型以及描述等。

例如:

{
    "type" : "object",
    "properties" : {
        "myArrayProperty" : {
            "type" : "array",
            "items" : {
                "type" : "string"
            }
        }
    }
}
           

生成的屬性:

List<String> myArrayProperty;
           

required

如果一個屬性在

required

中指定了,那麼這個屬性會有一個

Required

的注解,表明該屬性是必需的。

uniqueItems

這個就是我們上面表格中的用于區分

List

Set

的關鍵字了,如果我們定義的

array

中聲明

uniqueItems

true

,那麼最終轉換為的屬性的類型就為

Set

enum

對于枚舉類型的定義需要使用到此關鍵字,比如:

{
    "type" : "object",
    "properties" : {
        "myEnum" : {
            "type" : "string",
            "enum" : ["one", "secondOne", "3rd one"]
        }
    }
}
           

生成的枚舉類:

@Generated("com.googlecode.jsonschema2pojo")
    public static enum MyEnum {

    ONE("one"),
    SECOND_ONE("secondOne"),
    _3_RD_ONE("3rd one");
    private final String value;

    private MyEnum(String value) {
        this.value = value;
    }

    @JsonValue
    @Override
    public String toString() {
        return this.value;
    }

    @JsonCreator
    public static MyObject.MyEnum fromValue(String value) {
        for (MyObject.MyEnum c: MyObject.MyEnum.values()) {
            if (c.value.equals(value)) {
                return c;
            }
        }
        throw new IllegalArgumentException(value);
    }
}
           

default

如果我們需要某個屬性有預設值,可以加上此參數,生成類的屬性會自動執行個體化。具體可參照下表:

Json Schema | Java

myString : { “type”:“string”, “default”:“abc”} | myString : { “type”:“string”, “default”:“abc”};

myInteger : { “type”:“integer”, “default”:“100”} | private Integer myInteger = 100;

myNumber : { “type”:“number”, “default”:“10.3”}|private Double myNumber = 10.3D;

myMillis : { “type”:“string”, “format”:“utc-millisec”, “default”:“500”}|private Long myMillis = 500L;

myDate : { “type”:“string”, “format”:“date-time”, “default”:“500”}|private Date myDate = new Date(500L);

myDate : { “type”:“string”, “format”:“date-time”, “default”:“2011-02-24T09:25:23.112+0000”}|private Date myDate = new Date(1298539523112L);

myList : { “type”:“array”, “default”:[“a”,“b”,“c”]}|private List myList = new ArrayList(Arrays.asList(“a”,“b”,“c”));

title && description

title

description

用于描述一個屬性,當我們指定了這兩個參數時,

jsonschema2pojo

會在屬性的上面生成 Java 文檔,并且

title

description

之上。

format

format

jsonschema2pojo

提供給我們擴充更多類型的一個參數,在上面介紹的

type

中可以看到我們生成的 Java 類型并不多,像 Date 等這些參數都沒有,但是當我們加上

jsonschema2pojo

能識别的

format

參數後,就可以擴充我們的屬性類型,具體參照:

Format value | Java Type

“date-time” | java.util.Date

“date” | String

“time” | String

“utc-millisec” | long

“regex” | java.util.regex.Pattern

“color” | String

“style” | String

“phone” | String

“uri” | java.net.URI

“email” | String

“ip-address” | String

“ipv6” | String

“host-name” | String

“uuid” | java.util.UUID

extends

使用

extends

關鍵字可以實作

Java

中的繼承。

比如,我們定義

flower.json

{
   "type" : "object"
}
           

然後定義

rose.json

,使其繼承自

flower

{
    "type" : "object",
    "extends" : {
        "$ref" : "flower.json"
    }
}
           

最終我們生成的 Rose.java 為以下内容:

public class Rose extends Flower {
    ....
}
           

$ref

$ref

關鍵字用于指定某一個屬性的引用來源,在

jsonschema2pojo

中支援以下協定:

  • http://, https://
  • file://
  • classpath:, resource:, java: (all synonyms used to resolve schemas from the classpath).

我們定義 API 的時候一般是需要引用到其他我們定義的

Json Schema

文檔。比如:

{
   "type" : "object",
   "properties" : {
      "loggedInUser" : {
          "$ref" : "user.json"
      }
   }
}
           

表明

loggedInUser

屬性的類型是一個由

user.json

定義的類型。

{
   "description" : "Tree node",
   "type" : "object",
   "properties" : {
      "children" : {
         "type" : "array",
         "items" : {
             "$ref" : "#"
         }
      }
   }
}
           

這個表明

children

屬性引用的是該 object 自身,是以這可以生成一個 Tree 類型的類。

public class TreeNode {
   public List<TreeNode> getChildren() {...}

   public void setChildren(List<TreeNode> children) {...}
}
           

更多

  • javaEnumNames
    {
        "type" : "object",
        "properties" : {
            "foo" : {
                "type" : "string",
                "enum" : ["H","L"],
                "javaEnumNames" : ["HIGH","LOW"]
            }
        }
    }
               
    public enum Foo {
        HIGH("H"),
        LOW("L")
        ...
    }
               
  • javaInterfaces
    {
        "javaInterfaces" : ["java.io.Serializable", "Cloneable"],
        "type" : "object"
    }
               
    public class FooBar implements Serializable, Cloneable
    {
    ...
               
  • javaName
    {
      "type": "object",
      "properties": {
        "a": {
          "javaName": "b",
          "type": "string"
        }
      }
    }
               
    public class MyClass {
        @JsonProperty("a")
        private String b;
    
        @JsonProperty("a")
        public String getB() {
            return b;
        }
    
        @JsonProperty("a")
        public void setB(String b) {
            this.b = b;
        }
    }
               

聲明

本文絕大部分内容是引用的

jsonschame2pojo

的文檔,更多内容請看官方文檔 jsonschema2pojo.