使用google.gson工具时-JSON(谷歌)的使用


用法详解参考文章,点击这里

1. 创建GSON的两种方法

使用Gson的第一步是创建一个Gson对象,创建爱你Gson对象有两种方式:

  • 使用 new Gson()
  • 创建GsonBuilder实例,使用 create() 方法
    使用new Gson(),此时会创建一个带有默认配置选项的Gson实例,如果不想使用默认配置,那么就可以使用GsonBuilder。
//serializeNulls()是GsonBuilder提供的一种配置,当字段值为空或null时,依然对该字段进行转换
Gson gson = new GsonBuilder().serializeNulls().create(); 

使用GsonBuilder创建Gson实例的步骤:
首先创建GsonBuilder,然后调用GsonBuilder提供的各种配置方法进行配置,
最后调用GsonBuilder的create方法,将基于当前的配置创建一个Gson实例。
GsonBuilder的一些配置
参考文章,点击这里
详情配置,点击这里

 Gson gson = new GsonBuilder()
         .excludeFieldsWithoutExposeAnnotation() //不对没有用@Expose注解的属性进行操作
         .enableComplexMapKeySerialization() //当Map的key为复杂对象时,需要开启该方法
         .serializeNulls() //当字段值为空或null时,依然对该字段进行转换
         .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS") //时间转化为特定格式
         .setPrettyPrinting() //对结果进行格式化,增加换行
         .disableHtmlEscaping() //防止特殊字符出现乱码
         .registerTypeAdapter(User.class,new UserAdapter()) //为某特定对象设置固定的序列或反序列方式,自定义Adapter需实现JsonSerializer或者JsonDeserializer接口
         .create();

getAsString()方法返回JsonNull异常问题解决

概述
在使用google.gson工具时,JsonElement的getAsString()方法返回JsonNull异常问题。

问题描述
使用google.gson工具时经常会使用的就是反序列化功能。比如看下面的一个方法:

private static JsonParser parser= new JsonParser();

public String parseJsonString(String raw) {
   	JsonElement jsonElement = JSON_PARSER.parse(raw);
    JsonObject jsonObject = jsonElement.getAsJsonObject();
    JsonElement dataType = jsonObject.has("dataType")? jsonObject.get("dataType"): null;
    if(dataType != null) {
		return jsonObject.get("dataType").getAsString();
	}
	return "null";
}

上述代码执行到if语句处会判定dataType != null,实际上这个判断根本就无法过滤json为null的情况,比如有如下的json数据:

{
	"dataType": null
}

下述代码返回的结果为:

JsonElement dataType = jsonObject.has("dataType")? jsonObject.get("dataType"): null;
//因为json数据中有"dataType"键,所以jsonObject.has("dataType")会返回true,那么dataType的值就是jsonObject.get("dataType")的值,也就是上述json数据中的所谓的null

dataType实际上并不是所谓的java中的null,而是一种json所表征的null,它既不是字符串,同时dataType!=null会判为true,因为dataType中是存有数据的,它存的是一种表征json值为null的数据,因为dataType!=null会判为true,然后会进入if条件语句块执行getAsString(),那么此时会报JsonNull的异常。所以上述的判断语句不能只用dataType != null来做判断条件,还需要加一条专门用来判断json为null的语句,即:isJsonNull()方法,这是JsonElement类的非静态方法。所以下述条件判断才是正确的:

if(dataType != null && !dataType.isJsonNull()) {
	return jsonObject.get("dataType").getAsString();
}
//这一次则无法进入if语句块内部,因为:
dataType.isJsonNull()返回true,则
!dataType.isJsonNull()返回false

自定义的返回:setExclusionStrategies

	class Item {
		String name;
 
		@Expose
		public int age;
 
		public void gson() {
			// 过滤掉声明为 protcted 的变量
			Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
				
				@Override
				public boolean shouldSkipField(FieldAttributes f) {
					 //过滤掉字段名包含"age"
	                return f.getName().contains("age");
				}
				
				@Override
				public boolean shouldSkipClass(Class<?> clazz) {
					//过滤掉 类名包含 Bean的类
	                return clazz.getName().contains("Bean");
				}
			}).create();
		}
	}

公司项目中使用的实例:

如果你 Java 对象中包含一个正常的 Floats 或者 Doubles 类型的数据,是可以正常序列化得到 JSON的,如果你传入 Float.POSITIVE_INFINITY 值,Gson 将会抛出异常,因为这个值是不能符合 JSON 标准的
解决的办法就是通过 GsonBuilder 设置 serializeSpecialFloatingPointValues() 方法
参考文章,点击这里

 Gson gson = new GsonBuilder()
         .excludeFieldsWithoutExposeAnnotation() //不对没有用@Expose注解的属性进行操作
         .enableComplexMapKeySerialization() //当Map的key为复杂对象时,需要开启该方法
         .serializeNulls() //当字段值为空或null时,依然对该字段进行转换
         .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS") //时间转化为特定格式
         .setPrettyPrinting() //对结果进行格式化,增加换行
         .disableHtmlEscaping() //防止特殊字符出现乱码
         .registerTypeAdapter(User.class,new UserAdapter()) //为某特定对象设置固定的序列或反序列方式,自定义Adapter需实现JsonSerializer或者JsonDeserializer接口
         .create();
/*
 * Copyright (c) 2020. XiaoMi Inc. All Rights Reserved.
 * Authors: Sun Zhenkai <sunzhenkai@xiaomi.com>.
 * Created on 2020/3/13 14:54:39.
 */


import org.apache.thrift.TSerializer;
import org.apache.thrift.protocol.TSimpleJSONProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Type;

public class GsonUtils {

    private static final Logger logger = LoggerFactory.getLogger(GsonUtils.class);
    static GsonBuilder gsonBuilder = new GsonBuilder();
    private static final Gson gson = new Gson();

    public static final Gson gsoner = gsonBuilder
            .registerTypeAdapter(Double.class, new DoubleAdapter())
            .registerTypeAdapter(Float.class, new FloatAdapter())
            .setExclusionStrategies(new ExclusionStrategy() {
                                        @Override
                                        public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                                            return fieldAttributes.getName().equals("__isset_bit_vector");
                                        }

                                        @Override
                                        public boolean shouldSkipClass(Class<?> aClass) {
                                            return false;
                                        }

                                    }
            ).create();

    private static class DoubleAdapter implements JsonSerializer<Double> {

        @Override
        public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
            if (src == null || Double.isNaN(src) || Double.isInfinite(src)) {
                logger.warn("illegal double value [{}], use 0 instead", src);
                return gson.toJsonTree(0);
            } else {
                return gson.toJsonTree(src);
            }
        }
    }

    private static class FloatAdapter implements JsonSerializer<Float> {

        @Override
        public JsonElement serialize(Float src, Type typeOfSrc, JsonSerializationContext context) {
            if (src == null || Float.isNaN(src) || Float.isInfinite(src)) {
                logger.warn("illegal float value [{}], use 0 instead", src);
                return gson.toJsonTree(0);
            } else {
                return gson.toJsonTree(src);
            }
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值