转换格式属性配置
首先,我们需要对Json对象转换自定义些常用配置属性,封装成适合项目接口规则的工具类。代码如下:
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
// 日起格式化
private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
static {
//对象的所有字段全部列入
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//取消默认转换timestamps形式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//忽略空Bean转json的错误
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
//所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
objectMapper.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
//忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
}
}
对象与Json字符串之间的转换
一般对象与字符串之间的转换最为常用,代码实现如下:
/**
* 对象转Json格式字符串
* @param obj 对象
* @return Json格式字符串
*/
public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 对象转Json格式字符串(格式化的Json字符串)
* @param obj 对象
* @return 美化的Json格式字符串
*/
public static <T> String obj2StringPretty(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 字符串转换为自定义对象
* @param str 要转换的字符串
* @param clazz 自定义对象的class对象
* @return 自定义对象
*/
public static <T> T string2Obj(String str, Class<T> clazz){
if(StringUtils.isEmpty(str) || clazz == null){
return null;
}
try {
return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
上述三个方法实现起来也比较简单,满足了绝大多数业务接口开发,不过聪明的你们也想到了,在字符串转换对象的时候会存在一个坑,不用我说,你们也知道,就是在字符串与集合对象转换时会存在问题,那应该如何解决呢?
集合对象与Json字符串之间的转换
public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
if (StringUtils.isEmpty(str) || typeReference == null) {
return null;
}
try {
return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference));
} catch (IOException e) {
log.warn("Parse String to Object error", e);
return null;
}
}
public static <T> T string2Obj(String str, Class<?> collectionClazz, Class<?>... elementClazzes) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClazz, elementClazzes);
try {
return objectMapper.readValue(str, javaType);
} catch (IOException e) {
log.warn("Parse String to Object error : {}" + e.getMessage());
return null;
}
}
测试用例
实体类
public class User {
private Integer id;
private String email;
// 省略 set 和 get 方法
}
测试代码
@Slf4j
public class JsonUtilTest {
public static void main(String[] args) {
User user1 = new User();
user1.setId(1);
user1.setEmail("chenhaifei@163.com");
String userJsonstr = JsonUtil.obj2String(user1);
String userJsonPretty = JsonUtil.obj2StringPretty(user1);
log.info("userJson: {}", userJsonPretty);
User user2 = JsonUtil.string2Obj(userJsonstr, User.class);
user2.setId(2);
user2.setEmail("tianxiaorui@126.com");
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
String userListJson = JsonUtil.obj2String(userList);
List<User> userListBean = JsonUtil.string2Obj(userListJson, new TypeReference<List<User>>() {});
if (userListBean != null) {
userListBean.forEach(user -> {
System.out.println(user.getId() + " : " + user.getEmail());
});
}
List<User> userListBean2 = JsonUtil.string2Obj(userListJson, List.class, User.class);
if (userListBean2 != null) {
userListBean2.forEach(user -> {
System.out.println(user.getId() + " : " + user.getEmail());
});
}
}
}
其他json工具类
Google的Gson
Gson是目前功能最全的Json解析神器,Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。
而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。
类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。
Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。
1. bean转换json:toJson
Gson gson = new Gson();
String json = gson.toJson(obj);
- json转换bean:fromJson
Gson gson = new Gson();
String json = "{\"id\":\"2\",\"name\":\"Json技术\"}";
Book book = gson.fromJson(json, Book.class);
- json转换复杂的bean,比如List,Set : fromJson
// 将json转换成复杂类型的bean,需要使用TypeToken
Gson gson = new Gson();
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"java技术\"}]";
// 将json转换成List
List list = gson.fromJson(json, new TypeToken<List>() {}.getType());
// 将json转换成Set
Set set = gson.fromJson(json, new TypeToken<Set>() {}.getType());
- 通过json对象直接操作json以及一些json的工具
GsonBuilder gsonBuilder = new GsonBuilder();
ResponseData responseData = gsonBuilder.create().fromJson(result, ResponseData.class);
阿里巴巴的Fastjson
Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。
无依赖,不需要例外额外的jar,能够直接跑在JDK上。
FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。
FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。
1. bean转换json: toJSONString
map转json// 将对象转换成格式化的json
JSON.toJSONString(obj, true);
// 将对象转换成非格式化的json
JSON.toJSONString(obj, false);
// 对于复杂类型的转换,对于重复的引用在转成json串后在json串中出现引用的字符,比如
// $ref":"$[0].books[1]
Student stu = new Student();
Set books= new HashSet();
Book book = new Book();
books.add(book);
stu.setBooks(books);
List list = new ArrayList();
for(int i=0;i<5;i++) {
list.add(stu);
}
String json = JSON.toJSONString(list, true);
JSONObject json = JSONObject.parseObject(JSON.toJSONString(mainBrandMap));
- json转换bean:parseObject
String json = "{\"id\":\"2\",\"name\":\"Json技术\"}";
Book book = JSON.parseObject(json, Book.class);
- json转换复杂的bean,比如List,Map:parseObject
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"java技术\"}]";
// 将json转换成List
List list = JSON.parseObject(json, new TypeReference<ARRAYLIST>(){});
// 将json转换成Set
Set set = JSON.parseObject(json, new TypeReference<HASHSET>(){});
- 通过json对象直接操作json
String propertyName = 'id';
String propertyValue = "";
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject obj = JSON.parseObject(json);
propertyValue = obj.get(propertyName));
如何选择
在项目选型的时候可以使用Google的Gson和阿里巴巴的FastJson两种并行使用,
如果只是功能要求,没有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson将bean转换json确保数据的正确,使用FastJson将Json转换Bean//解析json报文
ServletInputStream inputStream = request.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
StringBuffer buffer = new StringBuffer();
String inputStr = "";
while ((inputStr = reader.readLine())!= null) {
buffer.append(inputStr);
}
String inputJson = buffer.toString();
inputJson = URLDecoder.decode(inputJson, "GBK");
JSONObject jsonObject = new JSONObject(inputJson);
JSONObject jsonObject2 = null;
String businessNo = jsonObject.getString("BusinessNo").trim();
if (businessNo != null && "P".equals(businessNo.substring(0, 1))) {
JSONArray jasonArray = jsonObject.getJSONArray("FieldList");
for (int i = 0; i < jasonArray.length(); i++) {
jsonObject2 = jasonArray.getJSONObject(i);
prpScoreDataModifyDto = new PrpScoreDataModifyDto();
prpScoreDataModifyDto.setSid(dbPrpScoreDataModify.getSid());
prpScoreDataModifyDto.setBusinessNo(businessNo);
prpScoreDataModifyDto.setPolicyNo(businessNo);
prpScoreDataModifyDto.setInputDate(new DateTime(new Date(), DateTime.YEAR_TO_SECOND));
prpScoreDataModifyDto.setStatus("0");
prpScoreDataModifyDto.setTarField(jsonObject2.getString("TarField").trim());
prpScoreDataModifyDto.setNewValue(jsonObject2.getString("NewValue").trim());
prpScoreDataModifyDto.setOldValue(jsonObject2.getString("OldValue").trim());
}
}