JsonConvert 0.2.0正式版 发布~
? ?--
? ? ? 时隔大半年才有自己业余的时间对JsonConvert进行了一次大更新。
? ? ? 更新内容:
? ? ? ? ???1、结构上进行大量的重构
? ? ? ? ? ?2、支持更全面的泛型解析
? ? ? ? ? ?3、支持json部分对象提取
? ? ? ? ? ?4、支持非空构造函数的类
? ? ? ? ? ?5、增加字段的具体类型配置
? ? ? ? ? ?6、增加功能但代码反而减少40%
?
? ? ? ??JsonConvert默认只提供支持最基本的类型:
? ? ? ? ? ? ? ? boolean--double、enum、Boolean--Double、String、以上类型的数组
?
?
下面介绍JsonConvert的使用方法:
? ? ? 一、常用方法:
public static class Record { public int id; public String name; public Record(){}}//--------------------------序列化对象---------------------Record record = ...;String json = JsonConvert.convertTo(record);//通常序列化后需要io操作, 所以提供了一个bytes方法调用byte[] bytes = JsonConvert.convertToUTF8Bytes(record);//--------------------------解析对象---------------------//解析单个对象使用convertFrom方法, 数组则使用convertArrayFromrecord = JsonConvert.convertFrom(json, Record.class);//------------------------解析部分json--------------------String str = "{id:18,data:{name:'haha',info:{qq:10001,birth:[1988,8,8]}}}";int[] birth = JsonConvert.convertFrom(str, "data.info.birth", int[].class);?
?
? ?解析时默认情况下Record的实例化是通过DefaultCreator进行创建的, 而DefaultCreator使用的是反射。
所以如果注重这点反射性能的话可以给Record注册一个Creator:
?
JsonFactory.register(Record.class, new Creator<Record>() { public Record create(Object... params) { return new Record(); }});?
? 注意: 所有JsonFactory.register的方法必须在第一次使用JsonConvert之前调用。
? ? ? 二、无默认构造类:
? ? ? ?通常JavaBean都会有个public无参数的构造函数, 但是如果有特殊情况或者JavaBean是第三方提供的。
在解析之前就必须给这个类注册一个带有@CreatorFields的Creator:
public static class Record {public final int id;public String name;public long qq;public Record(int id, String name) {this.id = id;this.name = name;}}JsonFactory.register(Record.class, new Creator<Record>() { @CreatorFields({"id", "name"})public Record create(Object... params) {int id = params[0] == null ? 0 : (Integer) params[0];return new Record(id, (String) params[1]);}});
? ? ? 刚开始准备把JsonCreator用annotation来表示, 考虑到如果类是第三方提供的, 就无法使用annotation。
? ? ? 三、JsonListener的使用:
? ? ? ??JsonListener作用于为简单的数据,json里属性值为字符串或者数值的都会使用JsonListener来解析或序列化。
JsonConvert默认只支持java的基本数据类型, 如果使用到例如Date、BigInteger这样的类需要事先注册:
JsonFactory.register(Date.class, new JsonListener<Date>() {private final JsonListener<Long> listener = JsonFactory.findListener(long.class);@Overridepublic void convertTo(JsonWriter out, Date value) {if (value == null) {out.writeNull();} else {listener.convertTo(out, value.getTime());}}@Overridepublic Date convertFrom(final JsonReader in) {Long value = listener.convertFrom(in);return value == null ? null : new Date(value);}@Overridepublic Class<Date> getType() {return Date.class;}});JsonFactory.register(BigInteger.class, new JsonListener<BigInteger>() {@Overridepublic void convertTo(JsonWriter out, BigInteger value) {if (value == null) {out.writeNull();} else {out.write(true, value.toString());}}@Overridepublic BigInteger convertFrom(JsonReader in) {char[] text = in.readValue();return text == null ? null : new BigInteger(new String(text));}@Overridepublic Class<BigInteger> getType() {return BigInteger.class;}});
?
如果需要时间格式化之类的可以自定义JsonListener通过@JsonRef注册给字段。
? ? ? ?之所以不提供Date类的JsonListener?是因为long/int就足以表示时间, 无需Dae这么大的对象传递。
? ? ? 四、@JsonRef/JsonField的使用:
? ? ? ? ? @JsonRef与JsonField提供的功能几乎一样(JsonField多了一个type)。 为什么需要JsonField类呢, 因为当JavaBean是第三方提供的话, 就无法使用@JsonRef给JavanBean进行设置, 只能依靠JsonField。
@JsonRef的定义:
public @interface JsonRef { /** 给字段取个别名 */ String alias() default ""; /** 解析/序列化时是否屏蔽该字段 */ boolean ignore() default false; /** 给指定的属性赋予特定的JsonListener */ Class<? extends JsonListener> listener() default JsonListener.class; /** * 如果setter getter方法不是简单的直接操作field则设为true, * 为false框架会直接调用field, 而不是method * 例如: public int getNumber(){ return number; } * 这种情况应该设置为false, 默认值也就是false; * public int getNumber(){ return number > 0 ? -1 : number; } * 这种不是直接返回number的情况应该设置为true * setter getter方法都一样 */ boolean indirect() default false;}
? ? 例如给某个字段指定JsonListener:
?
public class Record {//自定义实现JsonDateFormatListener @JsonRef(listener = JsonDateFormatListener.class)public Date time;}?
? ? ? 五、泛型的支持:
? ? ? ? ?在0.1版本里面支持只Class, ?新版开始支持Type。
? ? ? ?简单的泛型解析:
public class CaseRecord {private static final Type Type_1 = new GenericType<List<Integer>>() {}.getType();private static Type Type_2 = new GenericType<List<Map<Integer, String>>>() {}.getType();private static Type Type_3 = new GenericType<List<Map<Integer, String>>[]>() {}.getType();public static void main(String[] args) throws Throwable {String str1 = "[{1:'a',2:'b'},{3:'c',4:'d'}]";List<Map<Integer, String>> value1 = JsonConvert.convertFrom(str1, Type_2); System.out.println(value1); List<Integer> value2 = JsonConvert.convertFrom("[1,2,3,4,5]", Type_1);System.out.println(value2); String str2 = "[" + str1 + "]";List<Map<Integer, String>>[] obj2 = JsonConvert.convertFrom(str2, Type_3);System.out.println(JsonConvert.convertTo(obj2));List<Map<Integer, String>>[] obj3 = JsonConvert.convertArrayFrom(str2, Type_3);System.out.println(JsonConvert.convertTo(obj3));}}
? ? ?给类注入具体的解析类型:
public class A {public BaseRecord record;public List names;public Map<?, ?> address;}//注册实现类JsonFactory.register(A.class, new JsonField("record", RecordImpl.class); //注册具体的类型JsonFactory.register(A.class, new JsonField("names", new GenericType<ArrayList<String>>() {}.getType())); //注册具体的类型JsonFactory.register(A.class, new JsonField("address", new GenericType<Map<Integer, String>>() {}.getType()));?
?
? ??? 六、拦截器:
? ? ? ?JsonConvert 提供一个在解析后、序列化前调用的拦截器:
public interface JsonInterceptor<T> { //解析后调用 public T postDecode(T obj); //序列化之前调用 public T preEncode(T obj);}
? ?例如:
JsonFactory.register(Record.class, new JsonInterceptor<Record>(){public Record postDecode(Record obj) {if(obj.getTime() < 1) obj.setTime(System.currentTimeMillis());return obj;}public Record preEncode(Record obj) {return obj;}});?
? ??? 七、循环引用:
? ? ? ?JsonConvert?在几乎没有性能影响下使用栈支持简单的树型循环引用, 毕竟json的规范中无循环引用。
只有当解析类或序列化类存在循环的可能才会启动栈。
? ? ? ? ?? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ?parent
?? ? ? ? ??? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? / ? ? ? \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? / ? ? ? ? \
? ? ? ? ?? ?? ? ? ? ?????/ ? ? ? ? ? ?\
?? ? ? ? ??? ? ? ??? ? ? ? ? ? ? ? ?node1 ? ? ? node2
?? ? ? ? ??? ? ? ?? ? ? ? ???? ? ? ?/ ? \ ? ? ? ? ? ? ? / ? \
?? ? ? ? ??? ? ? ? ?? ? ? ? ??? ? ?/ ? ? \ ? ? ? ? ? ? / ? ? \
?? ? ? ? ??? ? ? ? ?? ??? ? ? ? ??/ ? ? ? \ ? ? ? ? ? / ? ? ? \
? ? ? ? ?? ? ? ?? ? ? ? ???child1 ? ?child2 ?child3 ? child4
? ? 如图树型引用就是child1只能引用node1、parent;node1只能引用parent。而child1不能引用node2、child2。
?
? ??? 八、压缩序列化:
? ? ? ?为了让输出的json字符串长度尽量减少, 可以进行以下设置:
? ? ? ? ? ? ? ? ??//输出字段名不需要引号。? ?
? ? ? ? ? 1、 ?JsonFactory.setFieldQutoable(false);
? ? ? ? ? ? ? ? ??//boolean 值以0、1输出。? ?
? ? ? ? ? 2、 ?JsonFactory.register(boolean.class, JsonBoolListener.JsonBoolHexListener.getInstance());
? ? ? ? ? ? ? ? ??//boolean[] 值以01010011字符串输出。? ?
? ? ? ? ? 3、 ?JsonFactory.register(boolean[].class, JsonBoolArrayListener.JsonBoolArrayHexListener.getInstance());
? ? ? ? ? ? ? ? ??//byte[] 值以16进制字符串输出。? ?
? ? ? ? ? 3、 ?JsonFactory.register(byte[].class, JsonByteArrayListener.JsonByteArrayHexListener.getInstance());
? ? ? ? ? ? ? ? ??//char[] 值以字符串输出。? ?
? ? ? ? ? 4、 ?JsonFactory.register(char[].class, JsonCharArrayListener.JsonCharArrayHexListener.getInstance());
?
? ??? 九、性能比较:
? ? ? ?目前fastjson是号称性能最好的json库, 下面是与fastjon 1.1.17版本简单性能的比较结果: ?
?
? ? 由结果看出jsonconvert性能比fastjson稍好些~
? ? 说明一点:?MediaContent是根据jvm-serializers提供的数据类
? ? ? ? ? ? ? ? ? ? MediaContent2跟MediaContent的区别只是将List<Image> images 改成 Image[] images.
?
? ? 附件提供test源码~~
?
? ? ? 十、Jsonconvert 0.2.0 源码与jar包路径:
? ? ? ? ? ? ??https://tendon.googlecode.com/svn/trunk/tendon.jsonconvert/tags/0.2.0/
?
?
?
?
?
?
?
?
?
?