一、空值转换-异常状况: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反序列化