目前比较流行的处理json数据的工具是Jackson和Fastjson,只有少数的公司使用Gson(一些公司对外部插件的安全性要求问题,如某些银行),这里对Gson的使用作个记录。
1、引进Gson jar包
<dependency>
  <groupId>com.google.code.gson</groupId>
  <artifactId>gson</artifactId>
  <version>2.8.6</version>
</dependency>
2、Gson工具类
Q: 直接Gson gson = new Gson; 也是可以使用的,那为什么要自己写Gson工具类呢?
A: 写工具类是为了统一处理一些特殊情况,如null值的处理等。
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
public final class GsonUtils {
  private static String DATE_TIME_PATTERN_DEFAULT = "yyyy-MM-dd HH:mm:ss";
  private static ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
    @Override
    protected DateFormat initialValue() {
      return new SimpleDateFormat(DATE_TIME_PATTERN_DEFAULT);
    }
  };
  private static TypeAdapter<BigDecimal> decimalTypeAdapter = new TypeAdapter<BigDecimal>() {
    @Override
    public BigDecimal read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(in.nextDouble());
      } catch (NumberFormatException e) {
        return BigDecimal.ZERO;
      }
    }
    @Override
    public void write(JsonWriter out, BigDecimal value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<BigInteger> bigIntegerTypeAdapter = new TypeAdapter<BigInteger>() {
    @Override
    public BigInteger read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return BigInteger.ZERO;
        }
        return BigInteger.valueOf(in.nextLong());
      } catch (NumberFormatException e) {
        return BigInteger.ZERO;
      }
    }
    @Override
    public void write(JsonWriter out, BigInteger value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<Double> doubleTypeAdapter = new TypeAdapter<Double>() {
    @Override
    public Double read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return 0d;
        }
        return in.nextDouble();
      } catch (NumberFormatException e) {
        return 0d;
      }
    }
    @Override
    public void write(JsonWriter out, Double value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<Float> floatTypeAdapter = new TypeAdapter<Float>() {
    @Override
    public Float read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return 0f;
        }
        return Float.parseFloat(String.valueOf(in.nextDouble()));
      } catch (NumberFormatException e) {
        return 0f;
      }
    }
    @Override
    public void write(JsonWriter out, Float value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<Long> longTypeAdapter = new TypeAdapter<Long>() {
    @Override
    public Long read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return 0L;
        }
        return in.nextLong();
      } catch (NumberFormatException e) {
        return 0L;
      }
    }
    @Override
    public void write(JsonWriter out, Long value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<Integer> integerTypeAdapter = new TypeAdapter<Integer>() {
    @Override
    public Integer read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return 0;
        }
        return in.nextInt();
      } catch (NumberFormatException e) {
        return 0;
      }
    }
    @Override
    public void write(JsonWriter out, Integer value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<Boolean> booleanTypeAdapter = new TypeAdapter<Boolean>() {
    @Override
    public Boolean read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return Boolean.FALSE;
        }
        return in.nextBoolean();
      } catch (IllegalArgumentException e) {
        return Boolean.FALSE;
      }
    }
    @Override
    public void write(JsonWriter out, Boolean value) throws IOException {
      out.value(value);
    }
  };
  private static TypeAdapter<Date> dateTypeAdapter = new TypeAdapter<Date>() {
    @Override
    public Date read(JsonReader in) throws IOException {
      try {
        if (in.peek() == JsonToken.NULL) {
          in.nextNull();
          return null;
        }
        return dateFormat.get().parse(in.nextString());
      } catch (IllegalArgumentException | ParseException e) {
        return null;
      }
    }
    @Override
    public void write(JsonWriter out, Date value) throws IOException {
      out.value(dateFormat.get().format(value));
    }
  };
  static class StringNullAdapter extends TypeAdapter<String> {
    @Override
    public String read(JsonReader reader) throws IOException {
      if (reader.peek() == JsonToken.NULL) {
        reader.nextNull();
        return "";
      }
      return reader.nextString();
    }
    @Override
    public void write(JsonWriter writer, String value) throws IOException {
      if (value == null) {
        writer.nullValue();
        return;
      }
      writer.value(value);
    }
  }
  static class NullStringToEmptyAdapterFactory<T> implements TypeAdapterFactory {
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
      Class<T> rawType = (Class<T>) type.getRawType();
      if (rawType != String.class) {
        return null;
      }
      return (TypeAdapter<T>) new StringNullAdapter();
    }
  }
  private static Gson gson;
  private GsonUtils() {
    gson = GsonSingleton.GsonFactory.getGson();
  }
  private enum GsonSingleton {
    GsonFactory;
    private Gson gsonInner;
    private GsonSingleton() {
      gsonInner = new GsonBuilder().registerTypeAdapter(Integer.class, integerTypeAdapter).registerTypeAdapter(Long.class,
        longTypeAdapter).registerTypeAdapter(Float.class, floatTypeAdapter).registerTypeAdapter(Double.class,
        doubleTypeAdapter).registerTypeAdapter(Boolean.class, booleanTypeAdapter).registerTypeAdapter(BigInteger.class,
        bigIntegerTypeAdapter).registerTypeAdapter(BigDecimal.class, decimalTypeAdapter).registerTypeAdapter(Date.class,
        dateTypeAdapter).registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory<String>()).setLenient().serializeNulls()
        //.setDateFormat(DATE_TIME_PATTERN_DEFAULT)
        .create();
    }
    public Gson getGson() {
      return gsonInner;
    }
  }
  public static JsonElement toJsonElement(Object obj) {
    return GsonSingleton.GsonFactory.getGson().toJsonTree(obj);
  }
  public static String toJsonStr(Object obj) {
    return gson.toJson(obj);
  }
  public static <T> T fromJson(String json, Class<T> classOfT) {
    return gson.fromJson(json, classOfT);
  }
  public static <T> T fromJson(String json, Type type) {
    return gson.fromJson(json, type);
  }
}
3、常用注解
@SerializedName("user_name")  //能指定该字段在JSON中对应的字段名称
@SerializedName(value = "name", alternate = {"name1","name2"})
@Expose //指定该字段是否能够序列化或者反序列化,默认的是都支持(true)
@Expose(serialize = false, deserialize = false)
@Since(1.0)代表从版本1.0之后才生效
@Until(0.9)代表着在0.9版本之前都是生效的
-——————————————————-
创建测试数据model
{
  "id": 1,
  "user_name": "zhangsan",
  "password": "123456qwe",
  "age": 12,
  "student": true,
  "balance1": 1.123,
  "balance2": 1.123,
  "balance": 1.456,
  "createTime": "2020-04-07T06:20:52.497+0000",
  "descr": "说明内容……",
  "sub": {
    "id": null,
    "user_name": "zhangsan",
    "password": "",
    "age": null,
    "student": null,
    "balance1": null,
    "balance2": null,
    "balance": null,
    "createTime": null,
    "descr": null
  },
  "subList": [
    {
      "id": 2,
      "user_name": "zhangsan",
      "password": "123456qwe",
      "age": 12,
      "student": true,
      "balance1": 1.123,
      "balance2": 1.123,
      "balance": 1.123,
      "createTime": "2020-04-07T06:20:52.497+0000",
      "descr": "说明内容……"
    },
    {
      "id": 3,
      "user_name": "zhangsan",
      "password": "123456qwe",
      "age": 12,
      "student": false,
      "balance1": 1.123,
      "balance2": 1.123,
      "balance": 1.456,
      "createTime": "2020-04-07T06:20:52.497+0000",
      "descr": ""
    }
  ]
}
测试结果
