2017年9月27日 星期三

Jackson @JsonFormat.lenient Date validate

前幾天遇到了Jackson convert String to Date 的問題,因為字串轉日期預設是寬容的 ( lenient = true ),所以會在盡量不出錯 ( ParseException ) 的狀況下容錯,但這樣卻會造成資料內容錯誤,例如:輸入字串 "2017-02-29",會輸出 Wed Mar 01 00:00:00 CST 2017

先介紹一下專案環境

  • Jersey2. RESTful Web Service.
  • Swagger. Autogenerate Document.
  • Gradle. Build, Test, Dependent management

build.gralde

compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: '2.25.1'
compile group: 'org.glassfish.jersey.ext', name: 'jersey-spring3', version: '2.25.1'
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.25.1'
compile group: 'io.swagger', name: 'swagger-core', version: '1.5.13'
compile group: 'io.swagger', name: 'swagger-jersey2-jaxrs', version: '1.5.13'

Solution

@JsonFormat(lenient = false)

可以參考 這裡,簡單來說,這個問題在 2016/11/4 就已經有人提 Issue 出來,並在同年 11/16 就已加入 2.9 版;只要將 jackson-annotations:2.8.5 升級至 2.9.0,@JsonFormat annotation 即可設定 lenient attribute。
但這裡遇到個問題,可以參考 這裡,升版後,會出現以下錯誤;因為 Swagger-core 1.5.13 depends on Jackson 2.8.5. 但 2.9.0 的某個 Method 被拿掉了。(這個問題後來在 Jackson 2.9.1 修復了)
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.introspect.AnnotatedMember.annotations()Ljava/lang/Iterable;

@JsonDeserialize(using = DateDeserializer.class)

後來考慮到 Jackson 2.9.x 穩定性問題,怕又會有什麼奇怪的錯誤,所以在不升版的情況下,繼承 JsonDeserializer 實作 Date 型態的反序列化,範例如下:
public class DateDeserializer extends JsonDeserializer {

    @Override
    public Date deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setLenient(false);
        String text = parser.getText();
        try {
            Date date = sdf.parse(text);
            return date;
        } catch (ParseException e) {
            throw new RuntimeException("Date Parse 錯誤! 請檢查格式與合法性");
        }
    }

}

2017年9月26日 星期二

Swagger v.s. apiDoc

Live Document

Swagger V.S. apidoc
Swagger Core - Java-related libraries for generating and reading Swagger definitions
Swagger UI to generate interactive web-based documentation
Swagger Codegen - Command-line tool for generating both client and server side code from a Swagger definition
Swagger Editor - Browser based editor for authoring Swagger definitions in YAML or JSON format

apiDoc creates a documentation from API annotations in your source code.

評估考量
  • 文件與程式邏輯同步性
  • 統一格式 (易用性、可讀性)
  • 學習成本 (門檻)
  • 版本修改紀錄
Swagger
優:
  • 定義明確的 OpenAPI Specification
  • 工具多 (基於 OpenAPI Specification)
  • 網路資源多
  • 同步性高
缺:
  • 學習成本高,入門不易
  • 必須是 Web Project
  • Project 必須引入 Swagger Library
apiDoc
  • Install
    npm install apidoc -g
  • Use
    apidoc -i /example -o /apidoc

優:
  • 類似 Javadoc 寫法
  • no need to inject third party library
  • have version change log
  • easy to convert apidoc to swagger [https://github.com/fsbahman/apidoc-swagger]
缺:
  • 註解行數多於程式碼
  • 註解終歸是註解,還是有與程式邏輯不同步的可能性