JSON,Javascript Object Notation,是一种轻量级的数据交换格式,
Gson 是google解析Json的一个开源框架,同类的框架fastJson,JackJson等等。Gson是一个Java库,它不仅可以把Java对象转化为Json格式,它也能将一段Json格式的字符串转化为相对于的Java对象。
https://mvnrepository.com/artifact/com.google.code.gson/gson
POJO,Plain Old Java Object,是一种简单的Java对象,一般就是有一些private属性及其属性getter、setter方法的类。这种对象只能用来装载数据,作为数据存储的载体,而不具有业务逻辑处理的能力。
alibaba.fastjson : fastjson序列化toJSONString和反序列化parseObject自定义对象时,自定义对象需要有set和get方法,并且要有默认的构造函数,意味着类中有有参构造函数的时候要显示的定义一个默认的无参构造函数。
Gson的创建方式
1..Gson gson = new gson();
2.通过GsonBuilder(),可以配置多种配置。
Gson gson = new GsonBuilder()
.setLenient()// json宽松,如果你开启了 lenient 方式,Gson 的只能帮我们忽略掉源码里标记的格式错误,如果你的 JSON 中有其他错误,Gson 将会抛出 MalformedJsonException 异常,这样你必须要检查下你的 JSON 数据的合法性。
.enableComplexMapKeySerialization()
//支持Map的key为复杂对象的形式,默认的key的序列化调用key的tostring()方法
.serializeNulls() //智能null
.setPrettyPrinting()// 调整序列化格式。输入更漂亮
.disableHtmlEscaping() //默认是GSON把HTML转义的,使用此选项可将可将Gson配置为按原样传递HTML字符
.create();
可以通过https://jsonlint.com/来验证json格式的合法性
om.google.gson.Gson 实例是线程安全的, 因此类实例初始化后可以多线程共享使用。
serializeNulls():
字段值为 null 时是否序列化
1、Gson 在 toJson 的时候,默认是不会对属性值为 null 的字段进行序列化的,即结果中不会包含它,可以使用 GsonBuild 的 serializeNulls 方法构建 Gson,这样就会对属性值为 null 的字段进行序列化。
2、实际应用中,是否对属性值为 null 的字段进行序列化,根据需求定即可,建议进行序列化。
/**
* 对象中为 null 的字段,是否实行序列化,为了降低 bug,应该保持一致
*/
public static void parserPOJOToJsonContainNull() {
/**
* Person 实体一共4个字段:Integer id、String name、Date birthday、Boolean isMarry
* 现在它的属性全部不进行赋值
*/
Person person = new Person();
/** 不对属性值为 null 的字段进行序列化,转换结果会为空*/
String personStr = new Gson().toJson(person);
/** 对属性值为 null 的字段进行序列化*/
String personStrFinal = new GsonBuilder().serializeNulls().create().toJson(person);
System.out.println(personStr);
//输出:{}
System.out.println(personStrFinal);
//输出:{"pId":null,"pName":null,"birthday":null,"isMarry":null}
/** 对于字段值为 null 的字符串,解析的时候也需要注意
* JsonElement get(String memberName) 的时候返回的就是 null
*/
JsonObject jsonObject = JsonParser.parseString(personStrFinal).getAsJsonObject();
System.out.println(jsonObject.get("name"));//输出:null
/**判断元素是否为 null*/
System.out.println(jsonObject.get("name").isJsonNull());
//输出:true
}
Gson toJson 与 fromJson
1、Gson 提供了 fromJson() 和 toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法.。
2、Gson 对象的 toJson 方法可以将基本数据类型、以及 java 对象、List、Map 等转为 json 格式的字符串。
3、Gson 对象的 fromJson 方法做与 toJson 相反的操作,将 json 格式的字符串转为基本数据类型、 POJO 对象、List、Map 等。
public static void parserJsonToBasicData() {
Gson gson = new Gson();
/*
* <T> T fromJson(String json, Class<T> classOfT) json:被解析的 json 字符串
* classOfT:解析结果的类型,可以是基本类型,也可以是 java对象类型
*/
int i = gson.fromJson("100", int.class);
double d = gson.fromJson("100.99", Double.class);
boolean b = gson.fromJson("true", boolean.class);
String s = gson.fromJson("爱你", String.class);
System.out.println(i + "\t" + d + "\t" + b + "\t" + s);
// 输出:100 100.99 true 爱你
}
// 基本类型 -> 转为 Json 字符串
public static void parserBasicDataToJson() {
Gson gson = new Gson();
/*
* String toJson(Object src) 将对象转为 json,如 基本数据、POJO 对象、以及 Map、List 等
*/
String jsonNumber = gson.toJson(100);
String jsonDouble = gson.toJson(100.99);
String jsonBoolean = gson.toJson(false);
String jsonString = gson.toJson("Tiger");
System.out.println(jsonNumber + "\t" + jsonDouble + "\t" + jsonBoolean + "\t" + jsonString);
// 输出:100 100.99 false "Tiger"
}
// 数组格式的 Json 字符串 - > 转为 数组
public static void parserJsonStrToArray() {
String jsonArrayStr = "[\"Java\",\"Android\",\"IOS\"]";
Gson gson = new Gson();
String[] strings = gson.fromJson(jsonArrayStr, String[].class);
for (int i = 0; i < strings.length; i++) {
System.out.print((i + 1) + ":" + strings[i] + "\t");
}
// 输出:1:Java 2:Android 3:IOS
System.out.println();
}
// 数组格式的 Json 字符串 - > 转为 List 列表
public static void parserJsonStrToList() {
String jsonArray = "[\"Java1\",\"Android2\",\"IOS3\"]";
Gson gson = new Gson();
/*
* 如果解析结果是普通对象,如 单纯的java,则可以使用 fromJson(String json, Class<T> classOfT)
* 如果解析结果是复杂类型,如 List<T> 这种,则应该使用 fromJson(String json, Type typeOfT) json:被转换的
* json 格式的字符串 typeOfT:解析结果类型
*/
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {
}.getType());
for (int i = 0; i < stringList.size(); i++) {
System.out.print((i + 1) + ":" + stringList.get(i) + "\t");
}
// 输出:1:Java1 2:Android2 3:IOS3
System.out.println();
}
// Java 对象 -> 转为 json 字符串
public static void parserPOJOToJson() {
Person person = new Person();
person.setpId(9527);
person.setpName("华安");
person.setBirthday(new Date());
person.setIsMarry(true);
Gson gson = new Gson();
/*
* String toJson(Object src) 将对象转为 json,如 基本数据、java 对象、以及 Map、List 等 注意:如果 java
* 对象某个属性的值为 null,则 toJson(Object src) 默认不会对它进行转化 结果字符串中不会出现此属性
*/
String jsonUser = gson.toJson(person);
System.out.println(jsonUser);
// 输出:{"pId":9527,"pName":"华安","birthday":"Nov 23, 2018 1:50:56
// PM","isMarry":true}
}
// Json 字符串 -> 转为 java 对象
public static void parserJsonToPOJO() {
/** 符合 json 格式的字符串 */
String personJson = "{\"pId\":9527,\"pName\":\"华安\",\"birthday\":\"Nov 23, 2020 22:58:56 PM\",\"isMarry\":true}";
Gson gson = new Gson();
/**
* <T> T fromJson(String json, Class<T> classOfT) json:被解析的 json 字符串
* classOfT:解析结果的类型,可以是基本类型,也可以是 POJO 对象类型,gson 会自动转换
*/
Person person = gson.fromJson(personJson, Person.class);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String personBirthday = dateFormat.format(person.getBirthday());
System.out.println("用户生日:" + personBirthday);
// 输出:用户生日:2018-11-23 13:50:56
// 可见日期字符串也能完美转换
}
// List 集合 -> 转为 json 字符串
// list 会被解析成 Json 数组,List 中的元素被解析成 json
public static void parserPOJOListToJson() {
Person person = new Person();
person.setpId(9527);
person.setpName("华安");
person.setBirthday(new Date());
person.setIsMarry(true);
Person person2 = new Person();
person2.setpId(8866);
person2.setpName("宁王");
List<Person> personList = new ArrayList<>();
personList.add(person);
personList.add(person2);
Gson gson = new Gson();
/*
* String toJson(Object src) 将对象转为 json,如 基本数据、java 对象、以及 Map、List 等 注意:如果 java
* 对象某个属性的值为 null,则 toJson(Object src) 默认不会对它进行转化 结果字符串中不会出现此属性
*/
String personListJson = gson.toJson(personList);
System.out.println(personListJson);
// 输出:[{"pId":9527,"pName":"华安","birthday":"Nov 23, 2018 2:05:58
// PM","isMarry":true},{"pId":8866,"pName":"宁王","isMarry":false}]
}
static class Person {
Integer id;
String name;
Date birthday;
Boolean isMarry;
public void setpId(int i) {
this.id = i;
}
public Date getBirthday() {
return this.birthday;
}
public void setIsMarry(boolean b) {
this.isMarry = b;
}
public void setBirthday(Date date) {
this.birthday = date;
}
public void setpName(String string) {
this.name = string;
}
}
JsonObject、JsonArray、JsonParser
1、JsonParser 将 json 格式的字符串解析为 JsonObject、JsonArray 对象。
//Json 格式字符串 -> 解析为 JSON 对象
public static void parserJsonStrToJsonObj() {
String jsonStr = "{\"pId\":9527,\"pName\":\"华安\",\"birthday\":\"Nov 23, 2018 1:50:56 PM\",\"isMarry\":true}";
/**JsonElement parse(String json)
* 如果被解析的字符串不符合 json 格式,则抛出异常*/
JsonObject jsonObject = JsonParser.parseString(jsonStr).getAsJsonObject();
/**JsonElement get(String memberName)
* 注意:如果 get 的 key 不存在,则返回 null,如果不加判断而进行取值的话,会抛:java.lang.NullPointerException
* */
Integer pId = jsonObject.get("pId").getAsInt();
String pName = jsonObject.get("pName").getAsString();
System.out.println(jsonObject);
//输出:{"pId":9527,"pName":"华安","birthday":"Nov 23, 2018 1:50:56 PM","isMarry":true}
System.out.println(pId + "\t" + pName);
//输出:9527 华安
}
public static void parserJsonStrToJsonArray() {
String jsonArrayStr = "[{\"pId\":9527,\"pName\":\"华安\",\"isMarry\":true},{\"pId\":8866,\"pName\":\"宁王\",\"isMarry\":false}]";
JsonArray jsonArray = JsonParser.parseString(jsonArrayStr).getAsJsonArray();
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
System.out.println((i + 1) + ":" + jsonObject + "\t\t" + jsonObject.get("pName").getAsString());
}
//输出:1:{"pId":9527,"pName":"华安","isMarry":true} 华安
//输出:2:{"pId":8866,"pName":"宁王","isMarry":false} 宁王
}
//手动 创建 JSON对象 并添加基本类型属性
public static void createJsonObj() {
/**
* JsonObject 添加基本类型属性使用 addProperty(String property, Number value)、 addProperty(String property, String value) 等
* JsonObject 添加复杂类型属性使用 add(String property, JsonElement value)
* JsonObject 与 JsonArray 都是 JsonElement 类的子类
* 提示:如果添加的 key 已经存在,则后面的会覆盖前面的
*/
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("pId", 9527);
jsonObject.addProperty("pName", "华安");
jsonObject.addProperty("isMarry", true);
/**
* JsonObject 取值使用 JsonElement get(String memberName),根据 JsonElement 可以获取任意类型
* JsonObject 可以直接获取 JsonArray:JsonArray getAsJsonArray(String memberName)
* JsonObject 可以直接获取 JsonObject:JsonObject getAsJsonObject(String memberName)
*/
System.out.println(jsonObject + "\t" + jsonObject.get("pName").getAsString());
//输出:{"pId":9527,"pName":"华安","isMarry":true} 华安
}
//创建 JSON 数组
public static void createJsonArray() {
String json1 = "{\"pId\":9527,\"pName\":\"华安\",\"isMarry\":true}";
String json2 = "{\"pId\":1200,\"pName\":\"安禄山\",\"isMarry\":false}";
JsonObject jsonObject1 = JsonParser.parseString(json1).getAsJsonObject();
JsonObject jsonObject2 = JsonParser.parseString(json2).getAsJsonObject();
JsonArray jsonArray = new JsonArray();
jsonArray.add(jsonObject1);
jsonArray.add(jsonObject2);
System.out.println(jsonArray);
//输出:[{"pId":9527,"pName":"华安","isMarry":true},{"pId":1200,"pName":"安禄山","isMarry":false}]
}
//删除 JsonObject 的某个属性
public static void delJsonObjproperty() {
String json = "{\"pId\":9527,\"pName\":\"华安\",\"isMarry\":true}";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
System.out.println("删除前:" + jsonObject);
//输出:删除前:{"pId":9527,"pName":"华安","isMarry":true}
/**
* JsonElement remove(String property)
* 用于删除 JsonObject 的属性,返回被删除的属性的值,原 JsonObject 会改变
* 与get取值同理,如果 remove 的属性值不存在,则返回 null
*/
String delProperty = jsonObject.remove("pName").getAsString();
System.out.println("删除 " + delProperty + " 后:" + jsonObject);
//输出:删除 华安 后:{"pId":9527,"isMarry":true}
}
//修改 JsonObject 属性,与添加一样使用 addProperty,当 key 已经存在时,会覆盖旧值
public static void updateJsonObjproperty() {
String json = "{\"currentOnlineNumber\":\"101\",\"name\":\"汪茂雄\"}";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
System.out.println("修改前:" + jsonObject);
jsonObject.addProperty("name", "赵丽颖");
System.out.println("修改后:" + jsonObject);
}
//获取 JsonObject 属性值
public static void getJsonObjproperty() {
String json = "{\"pId\":9527,\"pName\":\"华安\",\"Dog\":{\"dName\":\"小黄\",\"color\":\"yellow\"}}";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
System.out.println("操作对象:" + jsonObject);
/**
* JsonElement get(String memberName):如果 memberName 不存在,则返回 null
* 所以除非应用中明确知道key存在,否则应该加以判断
*/
Integer pId = jsonObject.get("pId").getAsInt();
System.out.println("pId=" + pId);
/** boolean has(String memberName)
* 判断 JsonObject 中是否存在某个 key*/
if (!jsonObject.has("name")) {
System.out.println("name 属性不存在...");
}
/**
* JsonObject 取值使用 JsonElement get(String memberName),根据 JsonElement 可以获取任意类型
* JsonObject 可以直接获取 JsonArray:JsonArray getAsJsonArray(String memberName)
* JsonObject 可以直接获取 JsonObject:JsonObject getAsJsonObject(String memberName)
*/
JsonObject dogJson = jsonObject.getAsJsonObject("Dog");
//如果对pid和pName使用getAsJsonObject会报java.lang.ClassCastException异常
//提示不能把基本类型强转为JsonObject
System.out.println(dogJson);
}
//实际应用中,如果业务比较复杂,则通常都会嵌套 json,如下所示
//[{"pId":110,"pName":"华安","Dog":{"dName":"小黄","color":"yellow"}},
//{"pId":120,"pName":"安禄山","Dog":{"dName":"阿毛","color":"red"}}]
public static void complexParsen() {
/**两只小狗 json 字符串*/
String dog1JsonStr = "{\"dName\":\"小黄\",\"color\":\"yellow\"}";
String dog2JsonStr = "{\"dName\":\"阿毛\",\"color\":\"red\"}";
/**将 json 字符串解析为 JsonObject 对象*/
JsonObject dog1Json = JsonParser.parseString(dog1JsonStr).getAsJsonObject();
JsonObject dog2Json = JsonParser.parseString(dog2JsonStr).getAsJsonObject();
/**创建两个用户的 JsonObject 对象*/
JsonObject user1Json = new JsonObject();
JsonObject user2Json = new JsonObject();
/**添加普通值*/
user1Json.addProperty("pId", 110);
user1Json.addProperty("pName", "华安");
/**添加JsonObject对象
* 注意:添加的对象,而不应该是符合 json 格式的字符串*/
user1Json.add("Dog", dog1Json);
user2Json.addProperty("pId", 120);
user2Json.addProperty("pName", "阿毛");
user2Json.add("Dog", dog2Json);
/**创建 JsonArray 用于存放 JsonObject
* 同样添加的应该是对象,而不应该是符合格式的字符串*/
JsonArray jsonArray = new JsonArray();
jsonArray.add(user1Json);
jsonArray.add(user2Json);
System.out.println(jsonArray);
//输出:[{"pId":110,"pName":"华安","Dog":{"dName":"小黄","color":"yellow"}},
//{"pId":120,"pName":"阿毛","Dog":{"dName":"阿毛","color":"red"}}]
//如果addProperty("Dog", dog1JsonStr);的话是下面的输出
//[{"pId":110,"pName":"华安","Dog":"{\"dName\":\"小黄\",\"color\":\"yellow\"}"},
//{"pId":120,"pName":"阿毛","Dog":"{\"dName\":\"阿毛\",\"color\":\"red\"}"}]
}
JsonReader和JsonWriter
JsonReader:从流中读取JSON(RFC 7159)编码的值。
JsonWriter:将JSON(RFC 7159)编码的值写入流。
JsonReader
是流式JSON解析器和拉解析器的示例。推送解析器解析JSON令牌并将它们推送到事件处理程序中。
它有助于将JSON(RFC 7159)编码值作为标记流读取。
它读取文字值(字符串,数字,布尔值和空值)以及对象和数组的开始和结束分隔符。
标记以深度优先顺序遍历,与它们在JSON文档中出现的顺序相同。
令牌的键是JsonToken.NAME类型。使用nextName()
方法获取密钥名称。
- 如果hasNext()方法
JsonReader
有更多的标记,则返回true 的hasNext()方法。 - 的PEEK()方法返回下一个令牌JSON,但不移动在它。
- 对
peek()
随后的多次调用将返回相同的JSON令牌。 - 可以使用
JsonToken
类的常量检查返回标记的类型。 - Array的开启和关闭括号
'['
,并']'
与检查beginArray()和endArray()方法。 - Object的开始和结束括号
'{'
,'}'
并使用beginObject()和endObject()方法进行检查。 - 确定令牌的类型后,获得令牌的使用方法的类似的值
nextLong()
,nextString()
,nextInt()
等。 - 空文字可以使用任何消耗
nextNull()
或skipValue()
。 - 所有
next....()
方法都返回当前标记的值,并将内部指针移动到下一个标记。 - 遇到未知名称时,严格的解析器应该失败并出现异常。宽松解析器应该调用
skipValue()
以递归方式跳过值的嵌套标记,否则可能会发生冲突。
private static void readJon() throws IOException {
StringBuilder sb = new StringBuilder();
try (JsonReader reader = new JsonReader(Files.newBufferedReader(Paths.get("a.json")))) {
reader.setLenient(true);
readJsonObject(reader, sb);
System.out.println(sb.toString());
}
}
public static void readJsonArray(JsonReader reader, StringBuilder sb) throws IOException {
reader.beginArray();
sb.append("[");
while (reader.hasNext()) {
readJson(reader, sb);
}
reader.endArray();
sb.append("]");
}
public static void readJsonObject(JsonReader reader, StringBuilder sb) throws IOException {
reader.beginObject();
sb.append("{");
while (reader.hasNext()) {
readJson(reader, sb);
}
reader.endObject();
sb.append("}");
}
public static void readJson(JsonReader reader, StringBuilder sb)throws IOException
{
JsonToken nextToken = reader.peek();
if (JsonToken.BEGIN_OBJECT.equals(nextToken)) {
readJsonObject(reader, sb);
} else if (JsonToken.NAME.equals(nextToken)) {
String name = reader.nextName();
sb.append(name + ":");
} else if (JsonToken.STRING.equals(nextToken)) {
String value = reader.nextString();
sb.append(value + ", ");
} else if (JsonToken.NUMBER.equals(nextToken)) {
long value = reader.nextLong();
sb.append(value + ", ");
} else if (JsonToken.NULL.equals(nextToken)) {
reader.nextNull();
} else if (JsonToken.BEGIN_ARRAY.equals(nextToken)) {
readJsonArray(reader, sb);
}
}
public static void writeJson() throws Exception {
try (JsonWriter writer = new JsonWriter(Files.newBufferedWriter(Paths.get("a.json"), StandardCharsets.UTF_8))) {
writer.beginObject();
writer.setIndent("\t");
writer.name("field");
writer.beginObject();
writer.name("value").value(1);
writer.name("desc").value("test");
writer.name("type").value("int");
writer.name("constraints");
writer.beginArray();
writer.value(1);
writer.value(2);
writer.value(3);
writer.endArray();
writer.endObject();
writer.endObject();
}
}
a.json为下面配置
{
"field": {
"value": 1,
"desc": "test",
"type": "int",
"constraints": [
1,
2,
3
]
}
}