標籤:需要 相容 div admin ddr receive create port extend
有些時候,我們在和外部系統互動的時候使用了json作為標準的資料交換格式,同時為了安全性考慮,增加了對報文的校正,因此我們需要確保序列化的時候參數有序且不多不少剛好,因為對外的API不像後台和前端互動一樣,相容即可,而是對嚴謹性的要求極高。jackson預設的機制是序列化的時候,先父類的屬性,然後再是子類的屬性按照定義的順序進行(fastjson則剛好相反,先序列化子類,然後序列化父類)。為了使用json的工具類,且達到有序的目的,之前特地研究了fastjson/jackson兩者的序列化特性,fastjson/jackson都有設定序列化順序的參數,也就是jackson @JsonProperty註解的index以及fastjson @JSONField註解的ordinal。實際設定了測試下來,感覺兩者都不生效或者有bug,總之行為比較怪異。之前記得jackson有個類層級的@JsonInclude註解可以設定要序列化的所有屬性,於是特地測試了,符合預期的要求,不過記錯了是JsonIgnoreProperties。結合繼承[email protected]註解,我們甚至可以完美的達到對於一個相同的屬性比如狀態,有些view要稱為orderStatus,另外一些稱為shippingStatus的目標,同時確保在service/mapper層,完全是情境無關的。jacksonJsonIgnoreProperties/JsonPropertyOrder在序列化和還原序列化時僅讀取當前類的註解,忽略父類的註解,這樣我們就可以做到行為的100%精確控制,同時儘可能的複用了父類的定義。
如下:
package tf56.lf.lfoms.model.pub;import java.io.Serializable;import java.util.List;import javax.validation.constraints.NotNull;import com.fasterxml.jackson.annotation.JsonFormat;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.annotation.JsonPropertyOrder;import lombok.Getter;import lombok.Setter;import tf56.lf.base.metadata.validate.ValidServices;import tf56.lf.common.util.JacksonHelper;import tf56.lf.lfoms.validate.group.Group;/** * @author admin * */@Getter@Setter@Deprecated@JsonPropertyOrder({"fromOutPartyType","receiverMobile","sessionBean"})@JsonIgnoreProperties({"businessPartId","omsPaymentCollectionList","requestOrderNo"})public class TmsCreateRequestOrderIQReqDTO extends TmsCreateRequestOrderMainReqDTO implements Serializable{ private static final long serialVersionUID = 8617922710046163090L; //費用list @ValidServices(services = Group.RQUERSTORDER_CREATE ) @NotNull @JsonFormat private List<CreateOmsPaymentCollectionReq> omsPaymentCollectionList; //貨物列表 @ValidServices(services = Group.RQUERSTORDER_CREATE ) @NotNull private List<CreateGoodsDOReq> goodsList; public static void main(String[] args) { TmsCreateRequestOrderIQReqDTO dto = new TmsCreateRequestOrderIQReqDTO(); System.out.println(JacksonHelper.toJSON(dto)); }}
在TmsCreateRequestOrderMainReqDTO類上設定了:
@JsonPropertyOrder({"sessionBean","fromOutPartyType","receiverMobile"})
@JsonIgnoreProperties({"senderMobile"})
輸出如下:
{"fromOutPartyType":null,"receiverMobile":null,"sessionBean":null,"tfSign":null,"senderPartyId":null,"senderName":null,"senderMobile":null,"fromDistrict":null,"fromAddress":null,"senderOrganization":null,"toOutPartyType":null,"receiverPartyId":null,"receiverPartyName":null,"toDistrict":null,"toAddress":null,"receiverOrganization":null,"carriersPartyId":null,"carriersCompany":null,"clientNumber":null,"transportMethod":null,"deliveryMethod":null,"isNeedReceipt":null,"receiptMethod":null,"receiptNum":null,"orderSource":null,"terminal":null,"memo":null,"goodsList":null}
不過總的來說,Jackson應該提供JsonProperties註解,畢竟僅提供ignore,不提供正向的總會有些時候無法直接滿足一樣,就像黑白名單一樣的道理。
不過這隻是解決了單項的序列化問題,還原序列化的時候,同樣需要解決。如果暴露的介面直接通過json requestbody映射進來,就只能定義一個一一對應的介面代理類來映射了。
jackson JsonPropertyOrder和@JsonIgnoreProperties註解