Json源码解析与使用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

目录介绍

  • 0.提问环节
  • 1.基本使用
    • 1.1 Gson对象创建
    • 1.2 生成Json字符串
    • 1.3 fromJson之Json数组转化为字符串数组
    • 1.4 toJson之字符串数组转为Json数组
    • 1.5 fromJson之Json数组转为List
    • 1.6 toJson之List转为Json数组
    • 1.7 toJson之List转为Json数组
    • 1.8 fromJson之Json数组转为List
  • 2.高级使用
    • 2.1 序列化和反序列化
    • 2.2 序列化
    • 2.3 反序列化
    • 2.4 字段过滤
    • 2.5 属性重命名
    • 2.6 个性化设置
    • 2.7 TypeAdapter
    • 2.8 JsonSerializer序列化接口
    • 2.9 JsonDeserializer反序列化接口
    • 3.0 将请求网络日志按照一定格式展示
  • 3.源码分析
    • 3.1 后期添加
  • 4.知识拓展

关于链接

1.基本使用

1.1 Gson对象创建

  • 1.1.1 直接通过new来创建对象
//通过构造函数来获取
Gson gson = new Gson();
//通过 GsonBuilder 来获取,可以进行多项特殊配置
Gson gson = new GsonBuilder().create();
  • 1.1.2 通过单利方式创建全局对象
private static Gson gson = null;

static {
    if (gson == null) {
        gson = new GsonBuilder()
                .setLenient()// json宽松
                .enableComplexMapKeySerialization()//支持Map的key为复杂对象的形式
                .serializeNulls() //智能null
                .setPrettyPrinting()// 调教格式
                .disableHtmlEscaping()
                .registerTypeAdapter(int.class, new JsonDeserializer<Integer>() {//根治服务端int 返回""空字符串
                    @Override
                    public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                        //try catch不影响效率
                        try {
                            return json.getAsInt();
                        } catch (NumberFormatException e) {
                            return 0;
                        }
                    }
                })
                .create();
    }
}

public static Gson getGson() {
    return gson;
}

1.2 生成Json字符串

  • 1.2.1 代码如下所示

    private void toJson() {
      JsonObject jsonObject = new JsonObject();
      jsonObject.addProperty("String", "leavesC");
      jsonObject.addProperty("Number_Integer", 23);
      jsonObject.addProperty("Number_Double", 22.9);
      jsonObject.addProperty("Boolean", true);
      jsonObject.addProperty("Char", 'c');
      //Log.e(TAG,jsonObject.getAsString());      //这个会崩溃
      Log.e(TAG,jsonObject.toString());
      Log.e(TAG,jsonObject+"");
      //{"String":"leavesC","Number_Integer":23,"Number_Double":22.9,"Boolean":true,"Char":"c"}
      //{"String":"leavesC","Number_Integer":23,"Number_Double":22.9,"Boolean":true,"Char":"c"}
    }
    
  • 1.2.2 addProperty方法

  • 支持String,boolean,char,Number(包含:int,long,float,double,byte,short)
public void addProperty(String property, String value) {
    add(property, createJsonElement(value));
}

public void addProperty(String property, Number value) {
    add(property, createJsonElement(value));
}

public void addProperty(String property, Boolean value) {
    add(property, createJsonElement(value));
}

public void addProperty(String property, Character value) {
    add(property, createJsonElement(value));
}
  • 1.2.3 通过 JsonObject 自己来构建一个 JsonElement
  • addProperty 方法底层调用的是 add(String property, JsonElement value) 方法,即将基本数据类型转化为了 JsonElement 对象,JsonElement 是一个抽象类,而 JsonObject 继承了 JsonElement ,因此我们可以通过 JsonObject 自己来构建一个 JsonElement
//注意这个方法返回JsonElement对象
private JsonElement createJsonElement(Object value) {
    return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value);
}
  • 1.2.4 json解析步骤
    • 首先获取JSON元素数组:JSONArray jsonArray = new JSONArray(jsonData);
    • 其次循环获取每个元素:JSONObject jsonObject = jsonArray.getJSONObject(index);
    • 每次循环保存名称相对应的值:String name = jsonObject.getString("name");

1.3 Json数组转化为字符串数组

private void jsonToArray() {
    //Json数组 转为 字符串数组
    String[] arr = {"2222","3333","4444","5555"};
    //這種崩潰
    //String jsonArray = "{\"2222\",\"3333\",\"4444\",\"5555\"}";
    //這種正常
    String jsonArray = "[\"2222\",\"3333\",\"4444\",\"5555\"]";
    String[] strings = gson.fromJson(jsonArray, String[].class);
    System.out.println("Json数组 转为 字符串数组: ");
    for (String string : strings) {
        Log.e(TAG,string);
    }
}

打印日志:
2222
3333
4444
5555

1.4 toJson之字符串数组转为Json数组

private void arrayToJson() {
    String jsonArray = "[\"2222\",\"3333\",\"4444\",\"5555\"]";
    //字符串数组 转为 Json数组
    jsonArray = gson.toJson(jsonArray, new TypeToken<String>() {}.getType());
    Log.e(TAG,jsonArray);

    //打印日誌
    //"[\"2222\",\"3333\",\"4444\",\"5555\"]"
}

1.5 fromJson之Json数组转为List

private void jsonToList() {
    //Json数组 转为 List
    String jsonArray = "[\"2222\",\"3333\",\"4444\",\"5555\"]";
    List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
    for (String string : stringList) {
        Log.e(TAG,string);
    }
}

1.6 toJson之List转为Json数组

private void listToJson() {
    String jsonArray = "[\"2222\",\"3333\",\"4444\",\"5555\"]";
    List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
    //List 转为 Json数组
    jsonArray = gson.toJson(stringList, new TypeToken<List<String>>() {}.getType());
    Log.e(TAG,jsonArray);
    //打印日誌
    //["2222","3333","4444","5555"]
}

1.7 toJson之List转为Json数组

private void listModelToJson() {
    Person model1 = new Person("yangChong", 25, true);
    Person model2 = new Person("doubi", 26, false);
    final ArrayList<Person> lists = new ArrayList<>();
    lists.add(model1);
    lists.add(model2);
    Gson gson = new Gson();
    String s = gson.toJson(lists);
    Log.e(TAG,s);
    //打印日志
    //[{"age":25,"name":"yangChong","sex":true},{"age":26,"name":"doubi","sex":false}]
}

1.8 fromJson之Json数组转为List

private void jsonToListMode() {
    String json = "[{\"age\":25,\"name\":\"yangChong\",\"sex\":true},{\"age\":26,\"name\":\"doubi\",\"sex\":false}]";
    Gson gson = new Gson();
    List<Person> list = gson.fromJson(json, new TypeToken<List<Person>>() {}.getType());
    for (Person person : list) {
        Log.e(TAG,person.toString());
    }
    //打印日志
    //Person{name='yangChong', age=25, sex=true}
    //Person{name='doubi', age=26, sex=false}
}

2.高级使用

2.1 序列化和反序列化

  • Gson 也提供了 toJson() 和 fromJson() 两个方法用于转化 Model 与 Json,前者实现了序列化,后者实现了反序列化。

2.2 序列化

  • 将model对象转变成json字符串
private void personModelToJson() {
    //序列化
    Person person = new Person("yangChong", 25, true);
    Gson gson = new Gson();
    String s = gson.toJson(person);
    Log.e(TAG,s);
    //打印日志
    //{"age":25,"name":"yangChong","sex":true}
}

2.3 反序列化

  • 将json字符串转变成model对象
private void jsonToPersonModel() {
    //反序列化
    String userJson = "{\"age\":25,\"name\":\"yangChong\",\"sex\":true}";
    Gson gson = new Gson();
    Person person = gson.fromJson(userJson, Person.class);
    Log.e(TAG,person.toString());
    //打印日志
    //Person{name='yangChong', age=25, sex=true}
}

2.5 属性重命名

2.6 个性化设置

gson = new GsonBuilder()            //builder构建者模式
        .setLenient()               //json宽松
        .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
        .setPrettyPrinting()        //格式化输出
        .serializeNulls()           //智能null
        //.setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")       //格式化时间
        .disableHtmlEscaping()      //默认是GSON把HTML转义的
        .registerTypeAdapter(int.class, new JsonDeserializer<Integer>() {
            //根治服务端int 返回""空字符串
            @Override
            public Integer deserialize(JsonElement json, Type typeOfT,
                                       JsonDeserializationContext context)
                    throws JsonParseException {
                //try catch不影响效率
                try {
                    return json.getAsInt();
                } catch (NumberFormatException e) {
                    return 0;
                }
            }
        })
        .create();

2.7 TypeAdapter

  • TypeAdapter 是一个泛型抽象类,用于接管某种类型的序列化和反序列化过程,包含两个抽象方法,分别用于自定义序列化和反序列化过程

  • 2.7.1 举个例子

  • 定义 TypeAdapter 的子类 UserTypeAdapter 来接管 User 类的序列化和反序列化过程
    这里设定当 User 类序列化时 Json 中的Key值都是大写字母开头,反序列化时支持“name”和“Name”两种不同的 Json 风格
public class UserTypeAdapter extends TypeAdapter<User> {

    /**
     * 序列化
     */
    @Override
    public void write(JsonWriter jsonWriter, User user) throws IOException {
        //流式序列化成对象开始
        jsonWriter.beginObject();
        //将Json的Key值都指定为大写字母开头
        jsonWriter.name("Name").value(user.getName());
        jsonWriter.name("Age").value(user.getAge());
        jsonWriter.name("Sex").value(user.isSex());
        //流式序列化结束
        jsonWriter.endObject();
    }

    /**
     * 反序列化
     */
    @Override
    public User read(JsonReader jsonReader) throws IOException {
        User user = new User();
        //流式反序列化开始
        jsonReader.beginObject();
        while (jsonReader.hasNext()) {
            switch (jsonReader.nextName()) {
                //首字母大小写均合法
                case "userName":
                case "name":
                case "Name":
                    user.setName(jsonReader.nextString());
                    break;
                case "age":
                    user.setAge(jsonReader.nextInt());
                    break;
                case "sex":
                    user.setSex(jsonReader.nextBoolean());
                    break;
            }

        }
        //流式反序列化结束
        jsonReader.endObject();
        return user;
    }

}
  • 2.7.2 序列化和反序列化
    ```

#### 2.8 JsonSerializer序列化接口

/**

  • 序列化过程
    */
    @SuppressLint("LongLogTag")
    private void toJsonSerializer() {
    Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new JsonSerializer() {
     @Override
     public JsonElement serialize(User user, Type type, JsonSerializationContext jsonSerializationContext) {
         JsonObject jsonObject = new JsonObject();
         jsonObject.addProperty("NameHi", user.getName());
         jsonObject.addProperty("Sex", user.isSex());
         jsonObject.addProperty("Age", user.getAge());
         return jsonObject;
     }
    
    }).create();
    User user = new User("leavesC", 24, true);
    String s = gson.toJson(user);
    Log.e(TAG,s);
    }
    ```

2.9 JsonDeserializer反序列化接口

/**
 * 反序列化过程
 */
private void toJsonDeserializer() {
    Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new JsonDeserializer<User>() {
        @Override
        public User deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
            JsonObject jsonObject = jsonElement.getAsJsonObject();
            String name = null;
            //同时支持 userName 和 name 两种情况
            if (jsonObject.has("userName")) {
                name = jsonObject.get("userName").getAsString();
            } else if (jsonObject.has("name")) {
                name = jsonObject.get("name").getAsString();
            }
            int age = jsonObject.get("age").getAsInt();
            boolean sex = jsonObject.get("sex").getAsBoolean();
            return new User(name, age, sex);
        }
    }).create();
    String json = "{\"userName\":\"leavesC\",\"sex\":true,\"age\":24}";
    User user = gson.fromJson(json, User.class);
    System.out.println();
    System.out.println(user);

    json = "{\"name\":\"leavesC\",\"sex\":true,\"age\":24}";
    user = gson.fromJson(json, User.class);
    System.out.println();
    System.out.println(user);
}

3.0 将请求网络日志按照一定格式展示

private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void printJson(String tag, String msg) {
    String message;
    try {
        if (msg.startsWith("{")) {
            JSONObject jsonObject = new JSONObject(msg);
            //最重要的方法,就一行,返回格式化的json字符串,其中的数字4是缩进字符数
            message = jsonObject.toString(4);
        } else if (msg.startsWith("[")) {
            JSONArray jsonArray = new JSONArray(msg);
            message = jsonArray.toString(4);
        } else {
            message = msg;
        }
    } catch (JSONException e) {
        message = msg;
    }
    if(isGoodJson(message)){
        printLine(tag, true);
        String[] lines = message.split(LINE_SEPARATOR);
        for (String line : lines) {
            Log.e(tag, "║ " + line);
        }
        printLine(tag, false);
    }
}

private static void printLine(String tag, boolean isTop) {
    if (isTop) {
        Log.e(tag, "Http---------------------");
    } else {
        Log.e(tag, "Http---------------------");
    }
}

private static boolean isGoodJson(String json) {
    if (TextUtils.isEmpty(json)) {
        return false;
    }
    try {
        new JsonParser().parse(json);
        return true;
    } catch (JsonSyntaxException e) {
        return false;
    } catch (JsonParseException e) {
        return false;
    }
}
  • 如图,日志格式如下所示:
  • image
关于我的博客
目录
相关文章
|
1月前
|
JSON 前端开发 搜索推荐
关于商品详情 API 接口 JSON 格式返回数据解析的示例
本文介绍商品详情API接口返回的JSON数据解析。最外层为`product`对象,包含商品基本信息(如id、name、price)、分类信息(category)、图片(images)、属性(attributes)、用户评价(reviews)、库存(stock)和卖家信息(seller)。每个字段详细描述了商品的不同方面,帮助开发者准确提取和展示数据。具体结构和字段含义需结合实际业务需求和API文档理解。
|
29天前
|
JSON 小程序 UED
微信小程序 app.json 配置文件解析与应用
本文介绍了微信小程序中 `app.json` 配置文件的详细
136 12
|
29天前
|
JSON 缓存 API
解析电商商品详情API接口系列,json数据示例参考
电商商品详情API接口是电商平台的重要组成部分,提供了商品的详细信息,支持用户进行商品浏览和购买决策。通过合理的API设计和优化,可以提升系统性能和用户体验。希望本文的解析和示例能够为开发者提供参考,帮助构建高效、可靠的电商系统。
39 12
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
JSON JavaScript 前端开发
一次采集JSON解析错误的修复
两段采集来的JSON格式数据存在格式问题,直接使用PHP的`json_decode`会报错。解决思路包括:1) 手动格式化并逐行排查错误;2) 使用PHP-V8JS扩展在JavaScript环境中解析。具体方案一是通过正则表达式和字符串替换修复格式,方案二是利用V8Js引擎执行JS代码并返回JSON字符串,最终实现正确解析。 简介: 两段采集的JSON数据因掺杂JavaScript代码导致PHP解析失败。解决方案包括手动格式化修复和使用PHP-V8JS扩展在JavaScript环境中解析,确保JSON数据能被正确处理。
|
1月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
52 0
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
133 2
|
4月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
100 1
|
4月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
86 0

热门文章

最新文章

推荐镜像

更多