一、空值轉換-異常狀況:java
Can not instantiate value of type [map type; class java.util.HashMap, [simple type, class java.lang.String] -> [simple type, class java.lang.String]] from JSON String; no single-String constructor/factory method json
解決方法,在ObjectMapper配置中增長: ``` mapper.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true) ;api
二、轉義字符-異常狀況: org.codehaus.jackson.JsonParseException: Illegal unquoted character ((CTRL- CHAR, code 9)): has to be escaped using backslash to be included in string value at [Source: java.io.StringReader@10cfc2e3; line: 1, column: 2461] 解決辦法,在ObjectMapper配置中增長: ``` mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true) ;
三、定義針對日期類型的反序列化時的數據格式 ``` mapper.getDeserializationConfig().setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));數組
jackson在http接口測試環境中的應用 這裏先簡單的作下jackson的介紹:jackson能夠很方便而且高效的將json對象轉化成Java對象,也能夠將Java對象轉換成json對象和xml文檔。Jackson有幾個顯著的特色:性能高,對於複雜對象和大數據量對象的序列化和反序列化,表現出比同類工具包(如gson,json-lib等)更優的性能;功能強,綁定全部JDK中的通用類以及Java Bean Class,Collection,Map和Enum;無依賴,除了JDK外無任何他依賴;徹底開源,而且有豐富的文檔和用戶羣體,便於自學。 在進行http請求的接口測試的過程當中,咱們須要靈活方便的處理http請求返回數據,使json串反序列化成爲java對象,這樣咱們才能方便地對返回數據進行校驗。如何試用jackson進行反序列化,網上內容不少,因此在此補贅述。我想重點說下在接口測試過程當中須要注意的點和可能會遇到的問題的解決辦法。 【注意點1】: 儘量使用開發人員使用的數據對象類做爲反序列化時的mapper類。 一般狀況下,瀏覽器在發送http請求向服務端應用請求數據的時候,客戶端應用都會依賴一個服務端的client包,以便於反序列化json數據後,造成用於vm模板的渲染所須要的java對象。這樣就爲咱們測試http接口提供了便利,咱們只須要在咱們測試應用中依賴這個client的jar包,就能夠方便的運用這些對象去組裝咱們的mapper。 【注意點2】: 當開發人員提供的數據對象類「很差用」的時候,須要自行建立pojo類,或者使用JDK的原生數據對象。 ObjectMapper初始化配置的代碼:
ObjectMapper objectMapper = newObjectMapper(); //配置爲true表示mapper接受只有一個元素的數組的反序列化 objectMapper.configure(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true); //配置爲false表示mapper在遇到mapper對象中存在json對象中沒有的數據變量時不報錯,能夠進行反序列化 objectMapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES,false); //新版的jackson設置mapper的方法,功能同上 objectMapper.getDeserializationConfig().without(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); //定義針對日期類型的反序列化時的數據格式 objectMapper.getDeserializationConfig().setDateFormat(newSimpleDateFormat("yyyy-MM-dd HH:mm:ss")); 下面是處理json的工具類代碼: public static <T> T getObjectFromJsonString(String jsonString, TypeReference<T> tr) { if(jsonString == null||"".equals(jsonString)){ returnnull; } else { try { return (T)objectMapper.readValue(jsonString, tr); }catch(Exception e) { e.printStackTrace(); } } return null; }瀏覽器
此方法採用了泛型,是爲了抽象json返回對象的數據類型,以便後續開發通用的測試驗證類 下面是調用類的方法的代碼:
actDO = JsonUtils.getObjectFromJsonString(jsonStr, new TypeReference<BaseResponseModel<PublishCommentResultMapper>>(){});app
或者
actDO = JsonUtils.getObjectFromJsonString(jsonStr, new TypeReference<BaseResponseModel<Map<String,String>>>() {});dom
下面是BaseResponseModel的代碼:
public class BaseResponseModel<T> implements Serializable{ private static final long serialVersionUID = 5393610697317077173L; private List<T> result; private boolean isSuccess; private String errorMsg; private int errorCode; private Integer total; //getter/setter省略 }eclipse
BaseResponseModel封裝了http請求返回的通用成員變量,例如:ErrorCode,IsSuccess,Total等 Mapper對象實例:
public class InfoAndRateMapper implements Serializable{ private static final long serialVersionUID = 1L; private List<BrandContentInfoDO> info; private List<Rate> rate; //getter/setter省略 }函數
常常碰到的問題及解決辦法: Exception1: Unrecognized field 「INFO」 (Class com.tmall.brand.api.test.model.InfoAndRateMapper), not marked as ignorable 【異常解釋】:當反序列化的json對象中有「INFO」,但mapper對象中沒有該字段時報錯。 【解決辦法】:在mapper中增長此變量 Exception2: Unrecognized field 「typeString」 【異常解釋】:反序列化過程當中出現不可識別的成員變量 【解決辦法】:增長mapper的屬性配置:objectMapper .configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);此參數默認是true,即檢查映射關係,當設置爲false之後,objectMapper將忽略需解析的json串中「不認識」的字段 例如:mapper對象中有private String name;的對象,當json對象中並無此變量,那當這個屬性值設置爲false時,可成功反序列化。 Exception3: org.codehaus.jackson.map.JsonMappingException : Can not instantiate value of type [collection type; class java.util.ArrayList, contains [simple type, class java.lang.Long]] from JSON String; no single-String constructor/factory method (through reference chain: com.tmall.brand.api.test.model.GetInfoAndRateRespModel["result"]->com.tmall.brand.api.test.model.InfoAndRateMapper["INFO"]->com.tmall.brand.service.domain.ratenews.BrandNewsQuery["typeList"]) 【異常解釋】:jackson沒法實例化json對象中變量類型的值 【解決辦法】:@JsonIgnoreProperties({ 「typeList」}) 在mapper類以前加此標籤忽略這個字段的反序列化 Exception4: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token 【異常解釋】:沒法反序列化沒有START_OBJECT token的ArrayList 【解決辦法】:增長mapper的屬性配置:
objectMapper.configure(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);工具
Exception5: org.codehaus.jackson.map.JsonMappingException : No suitable constructor found for type [simple type, class com.taobao.matrix.snsplugin.common.enumconstants.EnumResultStatus]: can not instantiate from JSON object (need to add/enable type information?) at [Source: java.io.StringReader@98350a; line: 1, column: 89] (through reference chain: com.tmall.brand.api.test.model.BaseResponseModel["result"]->com.tmall.brand.api.test.model.PublishCommentResultMapper["status"]) 【異常解釋】:jackson沒法實例化json對象,沒有找到適合的構造函數。 【解決辦法】:jackson在進行反序列號的時候,須要Mapper類是普通的pojo類,而且類中的變量都須要有setXXX的set方法,若是沒有set方法或者沒有「正確」的set方法,就會報沒法實例化JSON對象的異常 例如: 一、json對象的一個變量爲
private boolean isSuccess;
自動生成代碼後的set方法爲:(根據你本身的eclipse 的autogen來決定自動生成的代碼模板)
public void setSuccess(boolean isSuccess) { this.isSuccess = isSuccess; }
若是是這樣,jackson在反序列化的時候就會報此異常,應改成:
public void setIsSuccess( boolean isSuccess) { this.isSuccess = isSuccess; }
二、當JSON對象爲:
public class XXXStatus extends XXXResultStatus<XXXStatus>{ private static final long serialVersionUID = 2385584133823877965L;
public static final Map<Integer, XXXStatus> codeMap = newHashMap<Integer,XXXStatus>(); public static final XXXStatus SUCCESS = newXXXStatus(0,"xxx","xxx"); private XXXStatus(intcode,Stringmsg,StringfrontMsg){ super(code, msg, frontMsg); codeMap.put(code,this); } public static final XXXStatus getRelationStatus(intcode){ XXXStatus satus = codeMap.get(code); if(satus== null){ returnSYSTEM_ERROR; } returnsatus; } }
一樣沒有set方法,因此這樣的JSON對象都須要從新建立一個自定義的mapper對象,用於jackson反序列化