复杂的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