json操作在开发中虽不是难点,但是常用点,java操作json常用的是gson,jackjson,fastjson等等。jackjson采用单例模式,在解析性能方面,jackjson大概是gson性能的10倍左右,因此,相对更适合大数据处理。 今天我写这篇文章不是来探讨他们的性能,我更倾向于实际开发中的应用,把gson和jackjson在原有基础上进行封装,以使开发更简单。
gson和jackjson与.NET不同,.net里面json字符串反序列化对象不用严格区分大小写, java对json字符串解析有严格的大小写限制,这是我们开发中必须注意的,gson可在字段设置别名@SerializedName("name")来定义字段大小写,同样jackjson也可设置别名@JsonProperty("name")来定义解析属性大小写,对序列化和反序列化同样生效,好了,开始上代码:
Person类:
public class Person {
public Person(){};
public Person(String n,String e,int a,String c){
this.age=a;
this.Name=n;
this.Email=e;
this.classEs=c;
}
//@JsonProperty("nAme")
public String Name;
public String Email;
//@SerializedName("Age")
private int age;
private String classEs;
//@JsonProperty("nAme")
public String getName() {
return Name;
}
public void setName(String name) {
this.Name = name;
}
public String getClassEs() {
return classEs;
}
public void setClassEs(String classEs) {
this.classEs = classEs;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
this.Email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
gson对对象序列化是以属性名称为准,序列化结果与属性名称大小写一致,序列化结果为:{"Name":"sfdgg","Email":"sfdgs3com","age":45,"classEs":"ddfd"}。
jackjson则不同,他以公共属性方法为准,默认为驼峰命名显示,当属性全部为私有属性时,序列化结果为驼峰命名形式的json字符串,但是,当存在公共属性且公共属性不符合驼峰命名法规格的时候,他将会生成一个多余的字段与公共属性一致,如上面的结果为:{"Name":"sfdgg","Email":"sfdgs3com","age":45,"classEs":"ddfd","name":"sfdgg","email":"sfdgs3com"}。同时存在公共属性大小写结果Name和name,Email和email。
因此,gson对设置别名是在属性上面,jackjson中设置别名如果存在公共属性,则需要在公共属性及其对应的get方法上面同时设置别名,才能保持唯一,如果私有属性,只需要在get方法上面进行设置即可,反序列化则是在set方法进行设置。
好了,把封装方法的结果贴出来供大家方便使用,如有不对或需要改正的地方请大家批评指出,我会及时改正。
/**
* Gson 对象装json字符串
* @param 输入需要转化的对象
* @return 返回转化结果
*/
public static <T> String ObjToJson(T obj) {
if (obj == null) {
return "";
}
Gson gson = new Gson();
String jsonstr = gson.toJson(obj);
return jsonstr;
}
/**
* jackjson对象转字符串
* @param 输入的对象
* @return 转化结果
*/
public static <T> String MapObjToJson(T obj) {
if (obj == null) {
return "";
}
ObjectMapper objectMapper = new ObjectMapper();
String userMapJson = "";
try {
userMapJson = objectMapper.writeValueAsString(obj);
} catch (Exception e) {
return "";
}
return userMapJson;
}
Gson和jackjson对对象
序列化时,对象属性未赋值,Gson默认为序列化结果不显示,jackjson字符串则以属性结果为null进行序列化,反序列化则是gson不存在的结果为空值,jackjson则会报错,这一点要特别注意,可通过配置消除这种错误,默认空值,mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 。好多其他配置大家可以看看。
/**
* Gson字符串转对象
* @param 输入的需要转化的字符串
* @param 需要转化的对象类型
* @return 返回转化结果
* @throws InstantiationException
* @throws Exception
*/
public static <T> T JsonToObj(String jsonStr, Class<? extends T> c)
throws InstantiationException, Exception {
// Gson gson = new Gson();
Object obj = gson.fromJson(jsonStr, c);
T t = c.newInstance();
if (c.isInstance(obj)) {
t = (T) obj;
}
return t;
}
/**
* jackjson字符串转对象
* @param 输入的字符串
* @param 要转化的对象类型
* @return 转化结果
* @throws InstantiationException
* @throws Exception
*/
public static <T> T MapJsonToObj(String jsonStr, Class<? extends T> c)
throws InstantiationException, Exception {
ObjectMapper objectMapper = new ObjectMapper();
Object obj = objectMapper.readValue(jsonStr, c);
T t = c.newInstance();
if (c.isInstance(obj)) {
t = (T) obj;
}
return t;
}
有的时候我们想直接通过json字符串读取属性的结果,不想转化为对象再来读取value值,则可以通过一下几个方法。
/**
* jsckjson根据json字符串取属性结果,第一级目录
* @param 要搜索的字符串
* @param 搜索的属性名称(属性名称区分大小写)
* @return 搜过结果
*/
public static String getNodevalue(String jsonstr, String indexName) {
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode jnode = objectMapper.readTree(jsonstr);
return jnode.path(indexName).asText();
} catch (JsonProcessingException e) {
} catch (IOException e) {
}
return "";
}
第一级目录则是{"Name":"sfdgg","Email":"sfdgs3com","age":45,"classEs":"ddfd",
,"AAA":{"classEs":"ddfd","BBB","sfggf"}},要搜索属性名称BBB是无法找到的,要找到他必须通过下面方法,其实这两个方法该加上一个判断参数写成一个,既然现在是两个那就按照两个看吧:
/**
* 深度遍历搜索属性结果,搜索字符串所有节点
* @param 要搜过的字符串
* @param 要搜索的属性名称(属性名称区分大小写)
* @return 搜索的结果
*/
public static String getdeepNodevalue(String jsonstr, String indexName) {
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode jnode = objectMapper.readTree(jsonstr);
return jnode.findValue(indexName).asText();
} catch (JsonProcessingException e) {
} catch (IOException e) {
}
return "";
}
上面两个搜索属性名称都是区分大小写的,最后一个是不区分大小写的,全部遍历,一般用这个不太好:
/**
* 忽略大小写进行属性搜索
* @param 要搜索的字符串
* @param 搜过的属性名称(属性名称不区分大小写)
* @return 搜索的结果
*/
public static String getValueIgnoreCase(String jsonstr, String indexName) {
ObjectMapper objectMapper = new ObjectMapper();
try {
String result = "";
JsonNode jnode = objectMapper.readTree(jsonstr);
Iterator<String> keys = jnode.getFieldNames();
while (keys.hasNext()) {
String fieldName = keys.next();
if (fieldName.equalsIgnoreCase(indexName)) {
result = jnode.path(fieldName).asText();
break;
}
}
return result;
} catch (JsonProcessingException e) {
} catch (IOException e) {
}
return "";
}
终于写完了,这次发表的java的,下次发表一个.NET的,我的目的就是为了使开发更简单方便。好了,要睡觉了,明天还要上班,有啥不对的还请大家批评指出,不胜感激,谢谢。