fastjson 定制化解析

最近写了一个简单的定制解析。

fastjson 解析 Map key value时有bug.

public static class KVPair<K,V> {
        private K key;
        private V value;
        public KVPair(){}
        public KVPair(K key,V value){
            this.key = key;
            this.value = value;
        }
        public K getKey() {
            return key;
        }
        public void setKey(K key) {
            this.key = key;
        }
        public V getValue() {

            return value;
        }
        public void setValue(V value) {
            this.value = value;
        }
        
    }

这是一个简单的 KeyValue 类。这个类被fastjson解析出来的结果是:
public static void main(String[] args) {
        KVPair<String,String> kv = new KVPair<String,String>("aaa","bbb");
        System.out.println(JSON.toJSONString(kv));
    }


输出结果为:
{"key":"aaa","value":"bbb"}



在fastjson 1.1.23 版本时, 只要改动一下 setValue() 这个方法,就可以得到这样的解析结果:
改动后的 setValue(V value) 方法为:

public V setValue(V value) {
      this.value = value;
      return this.value;
}

输出结果为:
{"aaa":"bbb"}

这明显是 fastjson的bug。所以在1.1.46版本,已经不存在这个问题了。不管如何变化 setValue()函数,最后的输出结果仍然为:
输出结果:
{"key":"aaa","value":"bbb"}

现在问题来了。我更希望解析为下面的这种。
{"aaa":"bbb"}

这样占用的资源更少,并且也很清楚的表达了意思。这怎么写?fastjson提供的specialConfig 来提供特殊的序列化配置。

首先我们先对这个class创建一个特殊的序列化方法:

public static final SerializeConfig JSON_WRITE_CONFIG = new SerializeConfig();
    static {
        JSON_WRITE_CONFIG.put(KVPair.class,new KVPairSerailzer());
    }

然后我们来构造这个特殊的序列化类:
public class KVPairSerailzer implements ObjectSerializer{

    @SuppressWarnings("rawtypes")
    @Override
    public void write(JSONSerializer serializer,Object object,Object fieldName,Type fieldType) throws IOException {
        
        SerializeWriter out = serializer.getWriter();
        if (object ==null) {
            return ;
        }
        KVPair pair = (KVPair)object; 
        out.write("{");
        write(out,pair.getKey());
        out.write(":");
        write(out,pair.getValue());
        out.write("}");
    }
    
    public void write(SerializeWriter out,Object value) {
        if (value == null) {
            return;
        } else if (value instanceof Integer) {
            out.writeInt((Integer)value);
        } else if (value instanceof Long) {
            out.writeLong((Long)value);
        } else if (value instanceof String) {
            out.write("\"");
            out.write((String)value);
            out.write("\"");
        } else if (value instanceof Double) {
            out.write(Double.toString((Double)value));
        } else if (value instanceof Float) {
            out.write(Float.toString((Float)value));
        } else {
            throw new RuntimeException("not support value:"+value);
        }
    }

}


fastjson的逻辑是: 开始要传入一个序列化配置。这个序列化配置中有针对各个类如何进行序列化的子类(也就是映射关系)。如果我们将JSON_WRITE_CONFIG传入到序列化过程中,那么针对 KVPair.class这个类,就可以使用KVPairSerialzer()进行序列化。KVPairSerialzer在这个类需要继承ObjectSerializer,重要的是重构这个方法:
public void write(JSONSerializer serializer,Type fieldType)

这里只要获取 serializer.getWriter(),然后将序列化后的字符串写入到writer中就结束了。SerializerWriter 其实就是一个可变长char数组,细节没有什么好讲的。


另外 1.1.46 之前的版本如果不希望将某些field不放在序列化后的json中,需要加入一个 实现了PropertyPreFilter的类才行。例如下面这个类:

public class FieldJsonIgnoreFilter implements PropertyPreFilter  {
    private Set<String> excludes;

    @Override
    public boolean apply(JSONSerializer serializer,String name) {
        if(object instanceof ComputerCluster) {
            return !excludes.contains(name);
        }
        return true;
    }
    public FieldJsonIgnoreFilter() {
        this.excludes = Sets.newHashSet();
        
    }
    public void add(String excludeFieldName) {
        excludes.add(excludeFieldName);
    }
    
    public static final FieldJsonIgnoreFilter FIELD_JSON_IGNORE_FILTER = new FieldJsonIgnoreFilter();
    static {
        FIELD_JSON_IGNORE_FILTER.add("aaa");  // 如果fieldName 为 aaa 则不进行序列化。
        FIELD_JSON_IGNORE_FILTER.add("bbb");
        FIELD_JSON_IGNORE_FILTER.add("ccc");
        
    }
}

1.1.46版本之后只需要在在field上面加入Annotation.就可以实现上面的效果。

@JSONField(serialize=false)
private String aaa;

相关文章

文章浏览阅读2.4k次。最近要优化cesium里的热力图效果,浏览...
文章浏览阅读1.2w次,点赞3次,收藏19次。在 Python中读取 j...
文章浏览阅读1.4k次。首字母缩略词 API 代表应用程序编程接口...
文章浏览阅读802次,点赞10次,收藏10次。解决一个JSON反序列...
文章浏览阅读882次。Unity Json和Xml的序列化和反序列化_uni...