zoukankan      html  css  js  c++  java
  • json-lib(ezmorph)、gson、flexJson、fastjson、jackson对比,实现java转json,json转java

    本文中所讲的所有代码都在此:json-test

    目前关于java与json互转的工具包有很多 ,主流的主要有以下几个 :

    1. json-lib  (依赖于 ezmorph、commons-beanutils、commons-collections、groovy-all、oro、xom)
    2. gson
    3. flexjson
    4. fastjson
    5. jackson

    改天将各个工具包的特性(包括使用方便程度、序列化与反序列化的性能)列出来,便于大家使用,目前仅发现flexjson是最使用上简洁的、无依赖的工具包,能够轻松实现复杂的(树型多层结构,并且允许不同层对象中包含相同字段名)POJO转json。

    1、json-lib

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    // java -> json
    Classes sourceBean = TestCommon.getTestBean();
     
    JsonConfig jc = new JsonConfig();
    // 默认日期转换后的格式:"birthday":{"date":1,"day":3,"hours":0,"minutes":0,"month":0,"seconds":0,"time":-5364691200000,"timezoneOffset":-480,"year":-100}
    // 这里添加格式自定义转换,解决默认日期格式不堪直视的问题。不加也可以,json-lib会把Date中所有字段输出出来,搞晕你。。。
    jc.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
    // 过滤掉为空的属性,json-lib默认会将为空的String初始化为"",为空的Number初始化为0,总之不会为null。对于POJO来说,这种做法没法区分包装类型是否为空,所以某种意义上来说
    // ,json-lib多此一举了。
    jc.setJsonPropertyFilter(new PropertyFilter() {
     
        public boolean apply(Object source, String name, Object value) {
            if (value == null) {
                return true;
            }
            return false;
        }
    });
    JSONObject jsonObject = JSONObject.fromObject(sourceBean, jc);
    String jsonStr = jsonObject.toString();
    System.out.println("java->json:" + jsonStr);
     
    /** json -> java */
    JSONUtils.getMorpherRegistry().registerMorpher(
            new DateMorpher(new String[] { "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd" }));
     
    jc = new JsonConfig();
    jc.setRootClass(Classes.class); // 指定需要转换到的根类的类型。
    // 问题来了,那么内部集合对应的类型哪里指定呢?通过测试发现,如果不指定会出现只有父类(Classes)会转换成原始的Bean,而其集合(students)属性会被自动转换成MorphDynaBean,这时候如果迭代这个List中对象,会抛出异常:java.lang.ClassCastException:
    // net.sf.ezmorph.bean.MorphDynaBean cannot be cast to  com.zt.test.Student
    // 关于这个问题,官方并没有明确指明,但通过查看源码发现有一个方法能解决这个问题:JSONObject.setClassMap
    // ,该方法的官方声明【Sets the current attribute/Class Map ;classMap  : a Map of classes, every key identifies a property or a regexp 】
    // 通过查看源码发现这就是我们想要的,通过它可以指定内部集合中包含的复合对象的类型,如果该内部类型中还包含了其它集合,处理 方法一样,统统加如到classMap中去,如下:
     
    Map<String, Class> classMap = new HashMap<String, Class>();
    classMap.put("students", Student.class); //指定Classes的students字段的内部类型
    jc.setClassMap(classMap);
     
    JSONObject targetJo = JSONObject.fromObject(jsonStr, jc);
    Classes targetBean = (Classes) JSONObject.toBean(targetJo, jc);
     
    System.out.println("json->java:" + BeanUtils.describe(targetBean));
    assertEquals(targetBean.getStudents().get(0).getName(), "张扇风");

    2、gson

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
            package com.zt.test;
     
    import junit.framework.TestCase;
     
    import com.google.gson.Gson;
     
    public class GsonTest extends TestCase {
     
        public void testGson() throws Exception {
            Classes sourceBean = TestCommon.getTestBean();
            Gson gson = new Gson();
            // java -> json
            String json = gson.toJson(sourceBean);
    //      System.out.println(json);
     
            // json -> java
            Classes targetBean = gson.fromJson(json, Classes.class);
    //      System.out.println(BeanUtils.describe(targetBean));
            assertEquals(targetBean.getStudents().get(0).getName(), "张扇风");
            assertEquals(targetBean.getStudents().get(0).getBirthday(), TestCommon.DATEFORMAT.parse("1800-01-01 01:00:00"));
        }
     
        public void testLoad() throws Exception {
            for (int i = 0; i < 100000; i++) {
                testGson();
            }
        }
     
    }

    3、flex-json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // java -> json
            Classes sourceBean = TestCommon.getTestBean();
            JSONSerializer serializer = new JSONSerializer();
     
            String jsonStr = serializer.deepSerialize(sourceBean);
            //序列化的时候带着class字段,反序列化的时候就不需要指定目标class了。
            System.out.println("java -> json:" + jsonStr);
     
            // json -> java
            JSONDeserializer deserializer = new JSONDeserializer();
            Classes targetBean = (Classes) deserializer.deserialize(jsonStr);
            System.out.println("json -> java:" + BeanUtils.describe(targetBean) );
            assertEquals(targetBean.getStudents().get(0).getName(), "张扇风");

    4、fastjson

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
            package com.zt.test;
     
    import junit.framework.TestCase;
     
    import com.alibaba.fastjson.JSON;
     
    public class FastJsonTest extends TestCase{
        public void testFastJson() throws Exception {
            Classes sourceBean = TestCommon.getTestBean();
            // java -> json
            String json = JSON.toJSONString(sourceBean);
     
    //      System.out.println(json);
     
            // json -> java
            Classes targetBean = JSON.parseObject(json, Classes.class);
     
    //      System.out.println(BeanUtils.describe(targetBean));
            assertEquals(targetBean.getStudents().get(0).getName(), "张扇风");
            assertEquals(targetBean.getStudents().get(0).getBirthday(), TestCommon.DATEFORMAT.parse("1800-01-01 01:00:00"));
        }
     
        public void testLoad() throws Exception {
            for (int i = 0; i < 100000; i++) {
                testFastJson();
            }
        }
     
    }

    5、Jackson

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
            package com.zt.test;
     
    import junit.framework.TestCase;
     
    import com.fasterxml.jackson.databind.ObjectMapper;
     
    public class JacksonTest extends TestCase{
        public void testJackson() throws Exception {
            Classes sourceBean = TestCommon.getTestBean();
            // java -> json
            ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
     
            String json = mapper.writeValueAsString(sourceBean);
     
    //      System.out.println(json);
     
            // json -> java
            Classes targetBean = mapper.readValue(json, Classes.class);
     
    //      System.out.println(BeanUtils.describe(targetBean));
            assertEquals(targetBean.getStudents().get(0).getName(), "张扇风");
            assertEquals(targetBean.getStudents().get(0).getBirthday(), TestCommon.DATEFORMAT.parse("1800-01-01 01:00:00"));
        }
     
        public void testLoad() throws Exception {
            for (int i = 0; i < 100000; i++) {
                testJackson();
            }
        }
     
    }

    对比结果:

      依赖jar个数 上手容易度 功能、特性 性能  
    json-lib  5 java <-> json、xml<->json;
    自定义格式;
    属性过滤;
    25s  
    gson 1 java <-> json (待补充) 15s  
    flexjson 1 java <-> json(待补充) 12s  
    fastjson 1 java <-> json(待补充) 3s  
    jackson 1 java <-> json(待补充) 87s  
       
    性能测试:单个用例测试10W次java-json互转,测试多次取均速,测试非严格,只看相对性能就好,如果对测试结果有疑问的可以自己下载源码测试
  • 相关阅读:
    Go标准库之tar
    redis必知必会
    GORM CRUD指南
    GORM入门指南
    MUI中tap点击事件点击一次连续申请两次
    Go代码启动默认浏览器
    Go实现JWT
    Go Micro
    protobuf初识
    英语作文
  • 原文地址:https://www.cnblogs.com/daichangya/p/12958472.html
Copyright © 2011-2022 走看看