hibernate使用CGLIB把POJO的domain對象動態代理,實現它的魔法,可是給JSON的序列化帶來了麻煩,由於JSON沒法對lazy的屬性進行序列化。有如下的四個方法能夠解決hibernate的序列化問題java
domain類實現JSONString接口
json
創建JsonConfig實例,並配置屬性排除列表
app
用屬性過濾器
dom
寫一個自定義的JsonBeanProcessorthis
1. 實現JSONString接口是侵入性最強的方法spa
public class Person implements JSONString { 代理
private String name; code
private String lastname; 對象
private Address address;
// getters & setters
public String toJSONString() {
return "{name:'"+name+"',lastname:'"+lastname+"'}";
}
}
2.第二種方法經過jsonconfig實例,對包含和須要排除的屬性進行方便添加刪除
public class Person {
private String name;
private String lastname;
private Address address;
// getters & setters
}
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setExclusions( new String[]{ "address" } );
Person bean = /* initialize */;
JSON json = JSONSerializer.toJSON( bean, jsonConfig );
注意:這種方法不區分目標類,就是說若是有2個bean當中都存在「address」屬性,那麼採用這種方法,這兩個bean中的address屬性都將被排除
3. 使用propertyFilter能夠容許同時對須要排除的屬性和類進行控制,這種控制還能夠是雙向的,也能夠應用到json字符串到java對象
public class Person {
private String name;
private String lastname;
private Address address;
// getters & setters
}
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setJsonPropertyFilter( new PropertyFilter(){
public boolean apply( Object source, String name, Object value ){
// return true to skip name
return source instanceof Person && name.equals("address");
}
});
Person bean = /* initialize */;
JSON json = JSONSerializer.toJSON( bean, jsonConfig )
4. 最後來看JsonBeanProcessor,這種方式和實現JsonString很相似,返回一個表明原來的domain類的合法JSONOBJECT
public class Person {
private String name;
private String lastname;
private Address address;
// getters & setters
}
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.registerJsonBeanProcessor( Person.class,
new JsonBeanProcessor(){
public JSONObject processBean( Object bean, JsonConfig jsonConfig ){
if( !(bean instanceof Person) ){
return new JSONObject(true);
}
Person person = (Person) bean;
return new JSONObject()
.element( "name", person.getName() )
.element( "lastname", person.getLastname() );
}
});
Person bean = /* initialize */;
JSON json = JSONSerializer.toJSON( bean, jsonConfig );
And it is here with JsonBeanProcessors where we encounter the second gotcha related to CGlib. As you noticed we registered the processor using Person as target class, but Hibernate returns a Proxy that is not exactly a Person but a subclass (if possible) of Person. The default matching algorithm used by Json-lib will try to match the exact class (using equals), meaning that your processor will not be called when you expect it to be,this is why JsonBeanProcessorMatcher was introduced, now you are be able to write the following code
<textarea class="java:nocontrols:nogutter" cols="80" rows="34" name="srccode">public class Person { private String name; private String lastname; private Address address; // getters & setters } JsonConfig jsonConfig = new JsonConfig(); jsonConfig.registerJsonBeanProcessor( Person.class, new JsonBeanProcessor(){ public JSONObject processBean( Object bean, JsonConfig jsonConfig ){ if( !(bean instanceof Person) ){ return new JSONObject(true); } Person person = (Person) bean; return new JSONObject() .element( "name", person.getName() ) .element( "lastname", person.getLastname() ); } }); jsonConfig.registerJsonBeanProcessorMatcher( new JsonBeanProcessorMatcher(){ public Object getMatch( Class target, Set/*<Class>*/ matches ){ for( Object match : matches ){ if( ((Class)match).isAssignableFrom(target) ){ return match; } } return null; } }); Person bean = /* initialize */; JSON json = JSONSerializer.toJSON( bean, jsonConfig );</textarea>
I hope these examples help dispel some doubts, in any case please feel free to drop by Json-lib's forum and mailing lists.