錯誤警告信息描述:
net.sf.json.JSONObject.defaultBeanProcessing(JSONObject.java:769)
Property 'handler' of class com.vrv.cems.mgr.domain.Manager_$$_javassist_182 has no read method. SKIPPED
問題分析:
JsonUtil.bean2Json(queryHistogramVO,new String[]{})); 將VO對象轉換成JSON對象格式 jsonUtil包路徑: queryHistogramVO 對象的屬性和方法: public class HistogramVO { private Integer userNum; private Integer topCategory; private Integer lastUserNum; public Integer getCurrentUser() { return this.userNum; }
public Integer getTopCategory() { return topCategory; }
public void setTopCategory(Integer topCategory) { this.topCategory = topCategory; }
public void setUserNum(Integer userNum) { this.userNum = userNum; }
public Integer getLastUserNum() { return lastUserNum; }
public void setLastUserNum(Integer lastUserNum) { this.lastUserNum = lastUserNum; } }
肉眼看上去這個類沒有任何問題,仔細觀察發現 屬性"userNum"的get方法為"getCurrentUser()"
詳細分析:
1、jsonutil調用類圖分析:
JsonUtil工具類是通過JSONObject.fromObject()方法轉換的,查看源碼,對fromObject詳細分析發現代碼:
//這一句話很關鍵下面詳細講解
PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors( bean ); PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter(); Class beanClass = bean.getClass(); for( int i = 0; i < pds.length; i++ ){ String key = pds[i].getName(); if( exclusions.contains( key ) ){ continue; } if( jsonConfig.isIgnoreTransientFields() && isTransientField( key, beanClass ) ){ continue; } Class type = pds[i].getPropertyType(); //判斷如果類的get方法存在則設置屬性值
if( pds[i].getReadMethod() != null ){ //--------------中間的代碼省略掉
setValue( jsonObject, key, value, type, jsonConfig ); }else{ //當get方法不存在報警告錯誤
String warning = "Property '" + key + "' has no read method. SKIPPED"; fireWarnEvent( warning, jsonConfig ); log.warn( warning ); } }
PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors( bean );
這段代碼是獲取Bean所有的屬性信息並將他封裝成 PropertyDescriptor描述類。
深入 getPropertyDescriptors()分析:
if (beanClass == null) { throw new IllegalArgumentException("No bean class specified"); } // Look up any cached descriptors for this bean class
PropertyDescriptor[] descriptors = null; descriptors = (PropertyDescriptor[]) descriptorsCache.get(beanClass); if (descriptors != null) { return (descriptors); } // Introspect the bean and cache the generated descriptors
BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo(beanClass); } catch (IntrospectionException e) { return (new PropertyDescriptor[0]); } descriptors = beanInfo.getPropertyDescriptors(); if (descriptors == null) { descriptors = new PropertyDescriptor[0]; }
上面是關鍵部分,他是通過java內省機制獲取Bean的屬性方法,並返回BeanInfo類。
獲取屬性的規則:
1、類中包含 公有get方法如: public String getCurrUser()
2、類中包含公有的 set方法如:public void setName(String c)
通過上面的分析,HistogramVO類有setUserNum()方法確沒有對應的getUserNum()方法導致報""json.JSONObject - Property 'userNum' has no read method. SKIPPED"警告錯誤。
添加getUserNum()方法即解決問題。