複雜的json對象的解析思路,就是一層一層的解析出JSONObject,再從JSONObject中解析出JSONObject,直到能取到須要字段爲止html
ParseProcess是編程擴展定製反序列化的接口。fastjson支持以下ParseProcess:java
public static class VO { private int id; private Map<String, Object> attributes = new HashMap<String, Object>(); public int getId() { return id; } public void setId(int id) { this.id = id;} public Map<String, Object> getAttributes() { return attributes;} } ExtraProcessor processor = new ExtraProcessor() { public void processExtra(Object object, String key, Object value) { VO vo = (VO) object; vo.getAttributes().put(key, value); } }; VO vo = JSON.parseObject("{\"id\":123,\"name\":\"abc\"}", VO.class, processor); Assert.assertEquals(123, vo.getId()); Assert.assertEquals("abc", vo.getAttributes().get("name"));
public static class VO { private int id; private Map<String, Object> attributes = new HashMap<String, Object>(); public int getId() { return id; } public void setId(int id) { this.id = id; } public Map<String, Object> getAttributes() { return attributes; } } class MyExtraProcessor implements ExtraProcessor, ExtraTypeProvider { public void processExtra(Object object, String key, Object value) { VO vo = (VO) object; vo.getAttributes().put(key, value); } public Type getExtraType(Object object, String key) { if ("value".equals(key)) { return Integer.class; } return null; } } ExtraProcessor processor = new MyExtraProcessor(); VO vo = JSON.parseObject("{\"id\":123,\"value\":\"123456\"}", VO.class, processor); Assert.assertEquals(123,vo.getId()); Assert.assertEquals(123456,vo.getAttributes().get("value")); // value本應該是字符串類型的,經過getExtraType的處理變成Integer類型了。
SerializeFilter是經過編程擴展的方式定製序列化。fastjson支持6種SerializeFilter,用於不一樣場景的定製序列化。編程
public interface PropertyFilter extends SerializeFilter { boolean apply(Object object, String propertyName, Object propertyValue); }
能夠經過擴展實現根據object或者屬性名稱或者屬性值進行判斷是否須要序列化。例如:json
PropertyFilter filter = new PropertyFilter() { public boolean apply(Object source, String name, Object value) { if ("id".equals(name)) { int id = ((Integer) value).intValue(); return id >= 100; } return false; } }; JSON.toJSONString(obj, filter); // 序列化的時候傳入filter
和PropertyFilter不一樣只根據object和name進行判斷,在調用getter以前,這樣避免了getter調用可能存在的異常。app
public interface PropertyPreFilter extends SerializeFilter { boolean apply(JSONSerializer serializer, Object object, String name); }
若是須要修改Key,process返回值則可ide
public interface NameFilter extends SerializeFilter { String process(Object object, String propertyName, Object propertyValue); }
fastjson內置一個PascalNameFilter,用於輸出將首字符大寫的Pascal風格。 例如:性能
import com.alibaba.fastjson.serializer.PascalNameFilter; Object obj = ...; String jsonStr = JSON.toJSONString(obj, new PascalNameFilter());
public interface ValueFilter extends SerializeFilter { Object process(Object object, String propertyName, Object propertyValue); }
在序列化對象的全部屬性以前執行某些操做,例如調用 writeKeyValue 添加內容this
public abstract class BeforeFilter implements SerializeFilter { protected final void writeKeyValue(String key, Object value) { ... } // 須要實現的抽象方法,在實現中調用writeKeyValue添加內容 public abstract void writeBefore(Object object); }
在序列化對象的全部屬性以後執行某些操做,例如調用 writeKeyValue 添加內容spa
public abstract class AfterFilter implements SerializeFilter { protected final void writeKeyValue(String key, Object value) { ... } // 須要實現的抽象方法,在實現中調用writeKeyValue添加內容 public abstract void writeAfter(Object object); }
在fastjson中,支持一種叫作BeanToArray的映射模式。普通模式下,JavaBean映射成json object,BeanToArray模式映射爲json array。3d
class Mode { public int id; public String name; } Model model = new Model(); model.id = 1001; model.name = "gaotie"; // {"id":1001,"name":"gaotie"} String text_normal = JSON.toJSONString(model); // [1001,"gaotie"] String text_beanToArray = JSON.toJSONString(model, SerializerFeature.BeanToArray); // support beanToArray & normal mode JSON.parseObject(text_beanToArray, Feature.SupportArrayToBean);
上面的例子中,BeanToArray模式下,少了Key的輸出,節省了空間,json字符串較小,性能也會更好。
BeanToArray能夠局部使用,好比:
class Company { public int code; public List<Department> departments = new ArrayList<Department>(); } @JSONType(serialzeFeatures=SerializerFeature.BeanToArray, parseFeatures=Feature.SupportArrayToBean) class Department { public int id; public Stirng name; public Department() {} public Department(int id, String name) {this.id = id; this.name = name;} } Company company = new Company(); company.code = 100; company.departments.add(new Department(1001, "Sales")); company.departments.add(new Department(1002, "Financial")); // {"code":10,"departments":[[1001,"Sales"],[1002,"Financial"]]} String text = JSON.toJSONString(commpany);
在這個例子中,若是Company的屬性departments元素不少,局部採用BeanToArray就能夠得到很好的性能,而總體又可以得到較好的可讀性。
上一個例子也能夠這樣寫(推薦):
class Company { public int code; @JSONField(serialzeFeatures=SerializerFeature.BeanToArray, parseFeatures=Feature.SupportArrayToBean) public List<Department> departments = new ArrayList<Department>(); }
使用BeanToArray模式,能夠得到媲美protobuf的性能。
create ser deser total size +dfl protobuf 244 2297 1296 3593 239 149 json/fastjson_array/databind 123 1289 1567 2856 281 163 msgpack/databind 122 1525 2180 3705 233 146 json/fastjson/databind 120 2019 2610 4629 486 262 json/jackson+afterburner/databind 118 2142 3147 5289 485 261 json/jackson/databind 124 2914 4411 7326 485 261
這裏的json/fastjson_array/databind就是fastjson啓用BeanToArray模式,total性能比protobuf好,請看fastjson Benchmark