常见的json处理框架
Jackson
Spring 中常用的json处理框架,自动集成在其中。
共有三个核心包,Streaming、Databid、Annotations
Streaming在Jackson-core模块。定义了一些流处理相关的API以及特定的json
Annotations在 jackson-annotations模块,包含注解
Databid 在 jackson-databind 模块,在 Streaming 包的基础上实现了数据绑定,依赖于 Streaming 和 Annotations 包。
通常引入 jackson-databind 包就可以。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
当SpringBoot项目中引入以下依赖时不用再引入jackson依赖(内置)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
ObjectMapper是最常用的类
readValue()
进行反序列化,将常见的内容转换为java对象
writeValue()
进行序列化操作,将java对象转换为json对象
需要get/set方法
json转对象
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"username\":\"Jack\", \"age\": \"20\"}";
User user = objectMapper.readValue(json, User.class);
System.out.println("user = " + user);
}
json转list
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "[{\"username\":\"Jack\", \"age\": \"20\"},{\"username\":\"Tom\", \"age\": \"22\"}]";
List<User> userList = objectMapper.readValue(json, new TypeReference<List<User>>() {});
userList.forEach(System.out::print);
}
json转Map
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"username\":\"Jack\", \"age\": \"20\"}";
Map<String, Object> userNmp = objectMapper.readValue(json, new TypeReference<Map>() {});
for (Map.Entry<String, Object> entry : userNmp.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
字段忽略
如果在进行JSON 转 Java对象时,JSON中出现 Java 类中不存在的属性,那么在转换时会遇到com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
异常。
使用objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
配置可以忽略不存在的属性。
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"username\":\"Jack\", \"age\": \"20\",, \"test\": \"test\"}";
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
User user = objectMapper.readValue(json, User.class);
System.out.println("user = " + user);
}
日期处理
常用的java.util.Date类或时间类java.time.LocalDateTime类(JDK8),两者在Jackson中的处理略有不同。
ObjectMapper objectMapper = new ObjectMapper();
// 配置日期格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
Jackson配置
// 美化输出
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// 允许序列化空的POJO类
// (否则会抛出异常)
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// 把java.util.Date, Calendar输出为数字(时间戳)
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 在遇到未知属性的时候不抛出异常
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 强制JSON 空字符串("")转换为null对象值:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
// 在JSON中允许C/C++ 样式的注释(非标准,默认禁用)
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 允许没有引号的字段名(非标准)
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 允许单引号(非标准)
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 强制转义非ASCII字符
mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
// 将内容包裹为一个JSON属性,属性名由@JsonRootName注解指定
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
注解配置
- 属性使用的注解
@JsonProperty("NickName")//序列化后的json字段为NickName 反序列化也有效
private String name;
@JsonIgnore //标注的字段不参与序列化
@JsonGetter("jsonname") //序列化时自定义名字
@JsonSetter("javaname")// 反序列化时的设置 将某个字段反序列化时设置
- 实体类使用的注解
1、
//实体类使用的注解,用于序列化的时候忽略指定的一系列属性,或者反序列化的时候忽略未知的属性(没有getter/setter的属性)。
@JsonIgnoreProperties
序列化的时候,@JsonIgnoreProperties({"prop1", "prop2"}),忽略列表中的属性。
反序列化的时候,@JsonIgnoreProperties(ignoreUnknown=true),忽略没有get/set的属性。
2、
//实体类使用的注解,表示该类被忽略。
@JsonIgnoreType
- 公用注解
1、
//实体类/属性使用的注解,用于忽略NULL的属性,空的属性或者NULL的类。
@JsonInclude
2、
//实体类/属性使用的注解,在序列化或者反序列化的时候,指定属性格式化日期/时间。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",
timezone = "GMT+8")
private Date birthday;
FastJSON
Alibaba提供的开源库(效率很高)
pom引用
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
常用API
//把JSON文本parse为JSONObject或者JSONArray
public static final Object parse(String text);
//把JSON文本parse成JSONObject
public static final JSONObject parseObject(String text);
//把JSON文本parse为JavaBean
public static final <T> T parseObject(String text, Class<T> clazz);
//把JSON文本parse成JSONArray
public static final JSONArray parseArray(String text);
//把JSON文本parse成JavaBean集合
public static final <T> List<T> parseArray(String text, Class<T> clazz);
//将JavaBean序列化为JSON文本
public static final String toJSONString(Object object);
//将JavaBean序列化为带格式的JSON文本
public static final String toJSONString(Object object, boolean prettyFormat);
//将JavaBean转换为JSONObject或者JSONArray。
public static final Object toJSON(Object javaObject);
解析示例
public static void main(String[] args) {
String userJson = "{\"users\":[{\"name\":\"小白\",\"age\":\"12\"},{\"name\":\"大白\",\"age\":\"22\"}]}";
//将json字符串转换为jsonObject
JSONObject parseObject = JSON.parseObject(userJson);
// 获取json数组对象
JSONArray usersArray = parseObject.getJSONArray("users");
for (Object object : usersArray) {
JSONObject jsonObejct = (JSONObject) object;
String name = jsonObejct.getString("name");
String age = jsonObejct.getString("age");
System.out.println(name + "----" + age);
}
}
日期示例
//缺省会转为long 1401370199040
String dateJson = JSON.toJSONString(new Date());
//SerializerFeature.WriteDateUseDateFormat 默认格式
//"2014-05-29 21:36:24"
String dateJson = JSON.toJSONString(new Date(), SerializerFeature.WriteDateUseDateFormat);
//指定日期格式
//"2014-05-29 21:47:00.154"
String dateJson = JSON.toJSONStringWithDateFormat(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
设置输出null,直接输出是不包括null的
String listJson = JSON.toJSONString(map, SerializerFeature.WriteMapNullValue);
//输出
//{"a":null,"b":1}
GSON
Google的json处理框架
Gson具有三种API:数据绑定API,树模型API,流API
- 数据绑定API
数据绑定API使用属性访问JSON与POJO之间进行转换。GSON使用数据类型适配器处理json数据。类似于XML JAXB解析器 - 树模型API
创建JSON文档的内存树,它构建JSONElement的树。类似于XML DOM解析器。 - 流API
一种低级API,它使用JsonReader和JsonWriter作为离散记号读取和写入 JSON 内容。 这些类将数据读取为JsonTokens。 该 API 具有最低的开销,并且在读/写操作中速度很快。 它类似于 XML 的 Stax 解析器
pom引用
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
转换为json
toJson()
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
Gson gson = new Gson();
String output = gson.toJson(map);
System.out.println(output);
}
装换为指定类
fromJson()
public static void main(String[] args) {
String json_string = "{\"username\":\"Jack\", \"age\": \"20\"}";
Gson gson = new Gson();
User user = gson.fromJson(json_string, User.class);
System.out.println(user);
}
@ToString
@AllArgsConstructor
class User {
private String username;
private String age;
}
GsonBuilder
配置构建的GsonBuilder 最后使用create()
进行使用**此部分挺重要的**
其中的设置参考
- setFieldNamingPolicy 设置序列字段的命名策略(UPPER_CAMEL_CASE,UPPER_CAMEL_CASE_WITH_SPACES,LOWER_CASE_WITH_UNDERSCORES,LOWER_CASE_WITH_DASHES)
- addDeserializationExclusionStrategy 设置反序列化时字段采用策略ExclusionStrategy,如反序列化时不要某字段,当然可以采用@Expore代替。
- excludeFieldsWithoutExposeAnnotation 设置没有@Expore则不序列化和反序列化
- addSerializationExclusionStrategy 设置序列化时字段采用策略,如序列化时不要某字段,当然可以采用@Expore代替。
- registerTypeAdapter 为某特定对象设置固定的序列和反序列方式,实现JsonSerializer和JsonDeserializer接口
- setFieldNamingStrategy 设置字段序列和反序列时名称显示,也可以通过@Serializer代替
- setPrettyPrinting 设置gson转换后的字符串为一个比较好看的字符串
- setDateFormat 设置默认Date解析时对应的format格式
- serializeNulls() 设置打印输出null字段
public static void main(String[] args) throws UnsupportedEncodingException {
try (PrintStream prs = new PrintStream(System.out, true, "UTF8")) {
Gson gson = new GsonBuilder()
// 配置Gson在序列化和反序列化期间将特定的命名策略应用于对象的字段。
// 字段命名策略设置为FieldNamingPolicy.UPPER_CAMEL_CASE: 确保Java字段名称的第一个“字母”在序列化为其JSON形式时大写
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
User user = new User("Jack", 20);
gson.toJson(user, prs);
}
}
@ToString
@AllArgsConstructor
static
class User {
private String username;
private Integer age;
}
将json数据写入到json文件
这个写法是覆写,如果要使用追加需要调整输出流
public static void main(String[] args) throws IOException {
String filePath = "src/main/resources/users.json";
try (FileOutputStream fos = new FileOutputStream(filePath);
OutputStreamWriter isr = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
Gson gson = new Gson();
User user1 = new User("Jack", 23);
User user2 = new User("Jon", 22);
User user3 = new User("Tom", 33);
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
gson.toJson(users, isr);
}
JsonParser的一些用法
JsonParser类提供3种方法来提供JSON作为源并将其解析为JsonElements树。
- JsonElement parse(JsonReader json)–使用JsonReader读取JSON作为令牌流,并从JSON流中返回下一个值作为分析树。
- JsonElement parse(java.io.Reader json)–使用指定的阅读器读取JSON并将JSON字符串解析为解析树。
- JsonElement parse(java.lang.String json)–将指定的JSON字符串解析为解析树。
如果指定的文本不是有效的JSON,则这三个方法都将抛出JsonParseException和JsonSyntaxException。
JsonElement, JsonObject 和JsonArray
通过:
JsonElement jsonElement = new JsonParser().parse(json);
将json转为JsonElement后可通过以下方法判断具体类型:(返回值:boolean):
jsonElement.isJsonObject(); //是否为对象
jsonElement.isJsonArray(); //是否为数组
jsonElement.isJsonNull(); //是否为空
jsonElement.isJsonPrimitive(); //是否为java基本类型
然后可以解析为具体类型:
JsonObject jsonObject = jsonElement.getAsJsonObject();
JsonArray jsonArray = jsonElement.getAsJsonArray();
然后对JsonObject通过get方法提取字段
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class Main
{
public static void main(String[] args) throws Exception
{
String json = "{'id': 1001, "
+ "'firstName': 'Lokesh',"
+ "'lastName': 'Gupta',"
+ "'email': 'howtodoinjava@gmail.com'}";
JsonElement jsonElement = new JsonParser().parse(json);
JsonObject jsonObject = jsonElement.getAsJsonObject();
System.out.println( jsonObject.get("id") );
System.out.println( jsonObject.get("firstName") );
System.out.println( jsonObject.get("lastName") );
System.out.println( jsonObject.get("email") );
}
}
此外还有getAsJsonObject,getAsInt等方法
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(response);
JsonObject jsonObject = jsonElement.getAsJsonObject();
JsonObject data = jsonObject.getAsJsonObject("data");
jsonObject.get("status").getAsInt()
json处理框架对比帖:
Java 解析和处理 json 用哪个开源包最好? - 知乎 (zhihu.com)
找时间验证一下🏃🏃