fastjson快速上手(4)

0.复杂对象解析思路

复杂的json对象的解析思路,就是一层一层的解析出JSONObject,再从JSONObject中解析出JSONObject,直到能取到须要字段为止html

1. Fastjson API ParseProcess简介

ParseProcess是编程扩展定制反序列化的接口。fastjson支持以下ParseProcess:java

  • ExtraProcessor 用于处理多余的字段
  • ExtraTypeProvider 用于处理多余字段时提供类型信息

2. 使用ExtraProcessor 处理多余字段

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"));

3. 使用ExtraTypeProvider 为多余的字段提供类型

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类型了。

Fastjson API SerializeFilter

SerializeFilter是经过编程扩展的方式定制序列化。fastjson支持6种SerializeFilter,用于不一样场景的定制序列化。编程

  1. PropertyPreFilter 根据PropertyName判断是否序列化
  2. PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
  3. NameFilter 修改Key,若是须要修改Key,process返回值则可
  4. ValueFilter 修改Value
  5. BeforeFilter 序列化时在最前添加内容
  6. AfterFilter 序列化时在最后添加内容

PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化

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

PropertyPreFilter 根据PropertyName判断是否序列化

和PropertyFilter不一样只根据object和name进行判断,在调用getter以前,这样避免了getter调用可能存在的异常。app

public interface PropertyPreFilter extends SerializeFilter {
      boolean apply(JSONSerializer serializer, Object object, String name);
  }

NameFilter 序列化时修改Key

若是须要修改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());

ValueFilter 序列化是修改Value

public interface ValueFilter extends SerializeFilter {
      Object process(Object object, String propertyName, Object propertyValue);
  }

BeforeFilter 序列化时在最前添加内容

在序列化对象的全部属性以前执行某些操做,例如调用 writeKeyValue 添加内容this

public abstract class BeforeFilter implements SerializeFilter {
      protected final void writeKeyValue(String key, Object value) { ... }
      // 须要实现的抽象方法,在实现中调用writeKeyValue添加内容
      public abstract void writeBefore(Object object);
  }

AfterFilter 序列化时在最后添加内容

在序列化对象的全部属性以后执行某些操做,例如调用 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

在fastjson中,支持一种叫作BeanToArray的映射模式。普通模式下,JavaBean映射成json object,BeanToArray模式映射为json array。3d

Sample 1

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字符串较小,性能也会更好。

Sample 2

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就能够得到很好的性能,而总体又可以得到较好的可读性。

Sample 3

上一个例子也能够这样写(推荐):

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

相关文章
相关标签/搜索