首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

JsonConvert 0.2.0正式版 公布

2012-09-18 
JsonConvert 0.2.0正式版 发布~? ?--? ? ? 时隔大半年才有自己业余的时间对JsonConvert进行了一次大更新。?

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 0.2.0正式版 公布


JsonConvert 0.2.0正式版 公布

? ? 由结果看出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/

?

?

?

?

?

?

?

?

?

?

热点排行