zoukankan      html  css  js  c++  java
  • java中常见的json解析方法、库以及性能对比

    常见的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON库,阿里的fastjson,还有jackson,json-lib。

    1、java方法解析

    • JSONObject解析json对象
    • JSONArray解析json数组
      例如json字符串为:
    {
        "personData": [
            {
                "age": 12,
                "name": "nate",
                "schoolInfo": [
                    {
                        "School_name": "清华"
                    },
                    {
                        "School_name": "北大"
                    }
                ],
                "url": "http://pic.yesky.com/uploadImages/2014/345/36/E8C039MU0180.jpg"
            },
            {
                "age": 24,
                "name": "jack",
                ···
            }
        ],
        "result": 1
    }
    

    分析这段json数据,

    • 第一层是一个花括号括号,即jsonObect对象,然后这个对象里面有一个personData的JSONArray数组,以及一个result属性
    • 第二层personData的JSONArray数组,它里面除了属性之外,还有一个schoolInfo的JSONArray数组
    • 第三次是schoolInfo的JSONArray数组里面的JSONObject对象

    解析:

    public class Httpjson extends Thread {
        private String url;
        private Context context;
        private ListView listView;
        private JsonAdapter adapter;
        private Handler handler;
    
        public Httpjson(String url, ListView listView, JsonAdapter adapter, Handler handler) {
            super();
            this.url = url;
            this.listView = listView;
            this.adapter = adapter;
            this.handler = handler;
        }
    
        @Override
        public void run() {
            URL httpUrl;
            try {
                httpUrl = new URL(url);
                ···
        }
    
        /**
         * 从网络中获取JSON字符串,然后解析
         * @param json
         * @return
         */
        private List<Person> jsonParse(String json) {
            try {
                List<Person> personlist = new ArrayList<Person>();
                JSONObject jsonObject = new JSONObject(json);
                int result = jsonObject.getInt("result");
                if (result == 1) {
                    JSONArray jsonArray = jsonObject.getJSONArray("personData");
                    for (int i = 0; i < jsonArray.length(); i++) {
                        Person person = new Person();
                        JSONObject personData = jsonArray.getJSONObject(i);
                        int age = personData.getInt("age");
                        String url = personData.getString("url");
                        String name = personData.getString("name");
                        ···    
                        JSONArray schoolInfoArray = personData.getJSONArray("schoolInfo");
                        for (int j = 0; j < schoolInfoArray.length(); j++) {
                            JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j);
                            String schoolName = schoolInfojson.getString("School_name");
                            ···
                        }
                        ···
                    }
                    return personlist;
                } else {
                    Toast.makeText(context, "erro", Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
                Log.e("JsonParseActivity", "json解析出现了问题");
            }
    
            return null;
        }
    }
    

    2、gson解析

    (1)简介

    GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。

    (2)特点

    • 快速、高效
    • 代码量少、简洁
    • 面向对象
    • 数据传递和解析方便

    (3)编写bean类

    要写出能让gson使用的bean类,其中的key也就是名字,如date、safe这些必须一一对应起来。其次就是在bean类中,遇到花括号就写一个class类,遇到方括号就写一个Arraylist数组。这些就是主要规则了!内部的class类写成内部内的形式。

    • 内部嵌套的类必须是static的,要不然解析会出错;
    • 类里面的属性名必须跟Json字段里面的Key是一模一样的;
    • 内部嵌套的用[]括起来的部分是一个List,所以定义为 public List b,而只用{}嵌套的就定义为 public C c,
    {
        "date": "2014-04-23",
        ···       
        "name": "蘑菇街",
        "packageName": "com.mogujie",
        "safe": [
            {
                "safeDes": "已通过安智市场官方认证,是正版软件",
                ···
            },
            {
                "safeDes": "已通过安智市场安全检测,请放心使用",
                ···
            },
            {
                "safeDes": "无任何形式的广告",
               ···
            }
        ],
        "screen": [
            "app/com.mogujie/screen0.jpg",
            ···
        ],
        "size": 6746678,
        ···
    }
    
    public class GsonParseMoGuBean {
        
        public String data;    
        public String name;
        public String packageName;
        ···
        
        public ArrayList<SafeInfo> safe;
        
        public class SafeInfo {
            public String safeDes;
            ···                
        }
        
        public ArrayList<String> screen;
        
    }
    

    (4)将json格式的字符串{}解析为java对象

    Java对象
    
    /**
         * //将json格式的字符窜{}转换为java对象
         */
        private void jsonToJavaObjectByGson() {
            
            //1获取或创建json数据
            String json ="{
    " +
            "	"id":2, "name":"大虾", 
    " + 
            "	"price":12.3, 
    " +
            "	"imagePath":"http://192.168.10.165:8080/L05_Server/images/f1.jpg"
    " + 
            "}
    ";
            
            //2解析json数据
            Gson gson =new Gson();
            
            //第一个参数是要解析的数据,第二个参数是解析生成的java对象的类
            ShopInfo shopInfo =  gson.fromJson(json, ShopInfo.class);
            
        }
    

    (5)将json格式的字符串{}解析为java对象的list

    private void jsonToJavaListByGson() {
            
            //1获取或创建json数据
             String json = "[
    " + 
            "    {
    " + 
                     "        "id": 1,
    " + 
            "        "imagePath": "http://192.168.10.165:8080/f1.jpg",
    " + 
                     "        "name": "大虾 1",
    " + 
            "        "price": 12.3
    " +             "    },
    " +             "    {
    " +  
                     "        "id": 2,
    " + 
            "        "imagePath": "http://192.168.10.165:8080/f2.jpg",
    " +
            "        "name": "大虾 2",
    " + 
            "        "price": 12.5
    " +             "    }
    " +
            "]";
             
            
            //2解析json数据
             Gson gson =new Gson();      
             
             //List<ShopInfo>:是要返回数据的集合
             List<ShopInfo> shops = gson.fromJson(json,new TypeToken<List<ShopInfo>>(){}.getType());
             
            
            //3显示数据
             tv_gson_orignal.setText(json);
                
            tv_gson_last.setText(shops.toString());
            
        }
    

    (6)将java对象转换为json字符串

    private void javaToJSONByGson() {
            
            //1获取或创建java数据
            ShopInfo shopInfo = new ShopInfo(1,"鲍鱼",250.0,"baoyu");
            
            
            //2生成json数据
            Gson gson = new Gson();
            
            String json = gson.toJson(shopInfo);
            
            //3显示数据
             tv_gson_orignal.setText(shopInfo.toString());
                
                tv_gson_last.setText(json);
            
        }
    

    (7)将java对象的list转换为json字符串[]

    /**
         * //将java对象的list转换为json字符窜
         */
        private void javaToJSONArrayByGson() {
            
            //1获取或创建java数据
            List<ShopInfo> shops =new ArrayList<ShopInfo>();
            
            ShopInfo baoyu = new ShopInfo(1,"鲍鱼",250.0,"baoyu");
            
            ShopInfo longxia = new ShopInfo(1,"龙虾",250.0,"longxia");
            
            shops.add(baoyu);
            
            shops.add(longxia);
            
            //2生成json数据
            Gson gson = new Gson();
            
            String json = gson.toJson(shops);
            
            
            //3显示数据
             tv_gson_orignal.setText(shops.toString());
                
                tv_gson_last.setText(json);
        }
    

    3、fastjson

    (1)简介

    在日常的java项目开发中,JSON的使用越来越频繁,对于Json的处理工具也有很多。接下来就介绍一下阿里开源的一个高性能的JSON框架FastJson,功能完善,完全支持标准JSON库,现在已经越来越受到开发者的青睐。

    (2)特点

    Fastjson 是一个 Java 语言编写的高性能功能完善的 JSON 库。它采用一种“假定有序快速匹配”的算法,把JSONParse的性能提升到极致,是目前Java语言中最快的JSON库。

    (4)将 json 格式的字符串{}转换为 Java 对象

    private void jsonToJavaObjectByFastJson() {
    
    // 1 获取或创建 JSON 数据
     String json = "{
    " +
    "	"id":2, "name":"大虾", 
    " +
    "	"price":12.3, 
    " +
    "	"imagePath":"http://192.168.10.165:8080/L05_Server/images/f1.jpg "
    " +
    "}
    ";
    
    // 2 解析 JSON 数据
    ShopInfo shopInfo = JSON.parseObject(json, ShopInfo.class);
    
    }
    

    (4)将 json 格式的字符串[]转换为 Java 对象的 List

    private void jsonToJavaListByFastJson() {
    
    // 1 获取或创建 JSON 数据
     String json = "[
    " +
    " {
    "+
    " "id": 1,
    " +
    " "imagePath":
    "http://192.168.10.165:8080/f1.jpg",
    " +
    " " " " " "
    "name": "大虾 1",
    " +
    "price": 12.3
    " + },
    " +
    {
    "+
    "id": 2,
    " + "imagePath":
    "http://192.168.10.165:8080/f2.jpg",
    " +
    " "name": "大虾 2",
    " +
    " "price": 12.5
    " + " }
    "+
    "]";
    
    // 2 解析 JSON 数据
    List<ShopInfo> shopInfos = JSON.parseArray(json, ShopInfo.class);
    }
    

    (5)将 Java 对象转换为 json 字符串

    private void javaToJsonObjectByFastJson() {
    // 1 获取 Java 对象
    ShopInfo shopInfo = new ShopInfo(1, "鲍鱼", 250.0, "baoyu");
    // 2 生成 JSON 数据
    String json = JSON.toJSONString(shopInfo);
    // 3 数据显示 tv_fastjson_orignal.setText(shopInfo.toString()); tv_fastjson_last.setText(json);
    }
    

    (7)将 Java 对象的 List 转换为 json 字符串[]

    private void javaToJsonArrayByFastJson() {
    // 1 获取 Java 集合
    List<ShopInfo> shops = new ArrayList<>();
    ShopInfo baoyu = new ShopInfo(1, "鲍鱼", 250.0, "baoyu");
    ShopInfo longxia = new ShopInfo(2, "龙虾", 251.0, "longxia"); shops.add(baoyu);
    shops.add(longxia);
    // 2 生成 JSON 数据
    String json = JSON.toJSONString(shops);
    // 3 数据显示 tv_fastjson_orignal.setText(shops.toString()); tv_fastjson_last.setText(json);
    }
    

    4、性能对比

    选择一个合适的JSON库要从多个方面进行考虑:

    • 字符串解析成JSON性能
    • 字符串解析成JavaBean性能
    • JavaBean构造JSON性能
    • 集合构造JSON性能
    • 易用性
      编写性能测试
      接下来开始编写这四个库的性能测试代码。

    (1)添加maven依赖

    当然首先是添加四个库的maven依赖,公平起见,我全部使用它们最新的版本:

    <!-- Json libs-->
    <dependency>
        <groupId>net.sf.json-lib</groupId>
        <artifactId>json-lib</artifactId>
        <version>2.4</version>
        <classifier>jdk15</classifier>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.2</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.46</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.4</version>
    </dependency>
    

    (2)四个库的工具类

    java FastJsonUtil.java

    public class FastJsonUtil { public static String bean2Json(Object obj) { return JSON.toJSONString(obj); }
    
    public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
        return JSON.parseObject(jsonStr, objClass);
    }
    }
    

    java GsonUtil.java

    public class GsonUtil {
        private static Gson gson = new GsonBuilder().create();
    
        public static String bean2Json(Object obj) {
            return gson.toJson(obj);
        }
    
        public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
            return gson.fromJson(jsonStr, objClass);
        }
    
        public static String jsonFormatter(String uglyJsonStr) {
            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            JsonParser jp = new JsonParser();
            JsonElement je = jp.parse(uglyJsonStr);
            return gson.toJson(je);
        }
    }
    

    java JacksonUtil.java

    public class JacksonUtil { private static ObjectMapper mapper = new ObjectMapper();
    
    public static String bean2Json(Object obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
        try {
            return mapper.readValue(jsonStr, objClass);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    }
    
    

    java JsonLibUtil.java

    public class JsonLibUtil {
    
        public static String bean2Json(Object obj) {
            JSONObject jsonObject = JSONObject.fromObject(obj);
            return jsonObject.toString();
        }
    
        @SuppressWarnings("unchecked")
        public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
            return (T) JSONObject.toBean(JSONObject.fromObject(jsonStr), objClass);
        }
    }
    

    (3)准备Model类

    这里我写一个简单的Person类,同时属性有Date、List、Map和自定义的类FullName,最大程度模拟真实场景。

    public class Person {
        private String name;
        private FullName fullName;
        private int age;
        private Date birthday;
        private List<String> hobbies;
        private Map<String, String> clothes;
        private List<Person> friends;
    
        // getter/setter省略
    
        @Override
        public String toString() {
            StringBuilder str = new StringBuilder("Person [name=" + name + ", fullName=" + fullName + ", age="
                    + age + ", birthday=" + birthday + ", hobbies=" + hobbies
                    + ", clothes=" + clothes + "]
    ");
            if (friends != null) {
                str.append("Friends:
    ");
                for (Person f : friends) {
                    str.append("	").append(f);
                }
            }
            return str.toString();
        }
    
    }
    
    public class FullName {
        private String firstName;
        private String middleName;
        private String lastName;
    
        public FullName() {
        }
    
        public FullName(String firstName, String middleName, String lastName) {
            this.firstName = firstName;
            this.middleName = middleName;
            this.lastName = lastName;
        }
    
        // 省略getter和setter
    
        @Override
        public String toString() {
            return "[firstName=" + firstName + ", middleName="
                    + middleName + ", lastName=" + lastName + "]";
        }
    }
    

    (4)JSON序列化性能基准测试

    @BenchmarkMode(Mode.SingleShotTime)
    @OutputTimeUnit(TimeUnit.SECONDS)
    @State(Scope.Benchmark)
    public class JsonSerializeBenchmark {
        /**
         * 序列化次数参数
         */
        @Param({"1000", "10000", "100000"})
        private int count;
    
        private Person p;
    
        public static void main(String[] args) throws Exception {
            Options opt = new OptionsBuilder()
                    .include(JsonSerializeBenchmark.class.getSimpleName())
                    .forks(1)
                    .warmupIterations(0)
                    .build();
            Collection<RunResult> results =  new Runner(opt).run();
            ResultExporter.exportResult("JSON序列化性能", results, "count", "秒");
        }
    
        @Benchmark
        public void JsonLib() {
            for (int i = 0; i < count; i++) {
                JsonLibUtil.bean2Json(p);
            }
        }
    
        @Benchmark
        public void Gson() {
            for (int i = 0; i < count; i++) {
                GsonUtil.bean2Json(p);
            }
        }
    
        @Benchmark
        public void FastJson() {
            for (int i = 0; i < count; i++) {
                FastJsonUtil.bean2Json(p);
            }
        }
    
        @Benchmark
        public void Jackson() {
            for (int i = 0; i < count; i++) {
                JacksonUtil.bean2Json(p);
            }
        }
    
        @Setup
        public void prepare() {
            List<Person> friends=new ArrayList<Person>();
            friends.add(createAPerson("小明",null));
            friends.add(createAPerson("Tony",null));
            friends.add(createAPerson("陈小二",null));
            p=createAPerson("邵同学",friends);
        }
    
        @TearDown
        public void shutdown() {
        }
    
        private Person createAPerson(String name,List<Person> friends) {
            Person newPerson=new Person();
            newPerson.setName(name);
            newPerson.setFullName(new FullName("zjj_first", "zjj_middle", "zjj_last"));
            newPerson.setAge(24);
            List<String> hobbies=new ArrayList<String>();
            hobbies.add("篮球");
            hobbies.add("游泳");
            hobbies.add("coding");
            newPerson.setHobbies(hobbies);
            Map<String,String> clothes=new HashMap<String, String>();
            clothes.put("coat", "Nike");
            clothes.put("trousers", "adidas");
            clothes.put("shoes", "安踏");
            newPerson.setClothes(clothes);
            newPerson.setFriends(friends);
            return newPerson;
        }
    }
    

    说明一下,上面的代码中

    ResultExporter.exportResult("JSON序列化性能", results, "count", "秒");
    

    这个是我自己编写的将性能测试报告数据填充至Echarts图,然后导出png图片的方法,具体代码我就不贴了,参考我的github源码。

    执行后的结果图:

    从上面的测试结果可以看出,序列化次数比较小的时候,Gson性能最好,当不断增加的时候到了100000,Gson明细弱于Jackson和FastJson, 这时候FastJson性能是真的牛,另外还可以看到不管数量少还是多,Jackson一直表现优异。而那个Json-lib简直就是来搞笑的。_

    (5)JSON反序列化性能基准测试

    @BenchmarkMode(Mode.SingleShotTime)
    @OutputTimeUnit(TimeUnit.SECONDS)
    @State(Scope.Benchmark)
    public class JsonDeserializeBenchmark {
        /**
         * 反序列化次数参数
         */
        @Param({"1000", "10000", "100000"})
        private int count;
    
        private String jsonStr;
    
        public static void main(String[] args) throws Exception {
            Options opt = new OptionsBuilder()
                    .include(JsonDeserializeBenchmark.class.getSimpleName())
                    .forks(1)
                    .warmupIterations(0)
                    .build();
            Collection<RunResult> results =  new Runner(opt).run();
            ResultExporter.exportResult("JSON反序列化性能", results, "count", "秒");
        }
    
        @Benchmark
        public void JsonLib() {
            for (int i = 0; i < count; i++) {
                JsonLibUtil.json2Bean(jsonStr, Person.class);
            }
        }
    
        @Benchmark
        public void Gson() {
            for (int i = 0; i < count; i++) {
                GsonUtil.json2Bean(jsonStr, Person.class);
            }
        }
    
        @Benchmark
        public void FastJson() {
            for (int i = 0; i < count; i++) {
                FastJsonUtil.json2Bean(jsonStr, Person.class);
            }
        }
    
        @Benchmark
        public void Jackson() {
            for (int i = 0; i < count; i++) {
                JacksonUtil.json2Bean(jsonStr, Person.class);
            }
        }
    
        @Setup
        public void prepare() {
            jsonStr="{"name":"邵同学","fullName":{"firstName":"zjj_first","middleName":"zjj_middle","lastName":"zjj_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"Nike"},"friends":[{"name":"小明","fullName":{"firstName":"xxx_first","middleName":"xxx_middle","lastName":"xxx_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"Nike"},"friends":null},{"name":"Tony","fullName":{"firstName":"xxx_first","middleName":"xxx_middle","lastName":"xxx_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"Nike"},"friends":null},{"name":"陈小二","fullName":{"firstName":"xxx_first","middleName":"xxx_middle","lastName":"xxx_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"Nike"},"friends":null}]}";
        }
    
        @TearDown
        public void shutdown() {
        }
    }
    

    执行后的结果图:

    从上面的测试结果可以看出,反序列化的时候,Gson、Jackson和FastJson区别不大,性能都很优异,而那个Json-lib还是来继续搞笑的。

    转载声明:性能比较部分由客由熊能创作 © 飞污熊博客。

  • 相关阅读:
    ASP.Net请求处理机制初步探索之旅
    WebService如何调试及测试工具
    winform窗体间传值
    C# 窗体间传值方法大汇总
    c#写windows服务
    C# 公关类(全)
    简单的yoman generator
    Service Worker + Push API + Notification API实现桌面消息推送
    Service Worker
    HTML5桌面通知Notification
  • 原文地址:https://www.cnblogs.com/zyh0430/p/12009310.html
Copyright © 2011-2022 走看看