前言
最近在web项目当中使用了org.json这个库,使用它可以使用最简单的方式:
JSONObject obj = new JSONObject();
obj.put(key, value);
上面的代码是最简单的使用方式,还可以直接从将一个java对象转换成JSONObject对象,但是有些时候我们需要忽略掉其中的一些属性,也就是生成的JSONObject对象没有这个属性,其实org.json库本身提供了这个功能,只要数据为空就不会生成。
源码分析
先来看看最简单的java对象到JSONObject对象,这个库做了什么
先建好工程,然后建好Main函数所在的类和一个model类:
Test.java
package cn.karent;
public class Test {
private int age;
private String name;
private String address;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
上面是model类,下面是根据这个model生成json字符串的main函数:
Main.java
package cn.karent;
import org.json.JSONObject;
public class Main {
public static void main(String[] args) {
Test t = new Test();
t.setAge(10);
t.setName("wan");
t.setAddress("jiangxi");
JSONObject obj = new JSONObject(t);
System.out.println(obj);
}
}
结果:
{"address":"jiangxi","name":"wan","age":10}
下面来看源码分析,首先从JSONbject的构造器进去:
public JSONObject(Object bean) {
this();
this.populateMap(bean);
}
上面的构造函数什么也没有干,看起来应该是将转换都放在populateMap()方法里面,跟进去看看:
private void populateMap(Object bean) {
Class<?> klass = bean.getClass();
// If klass is a System class then set includeSuperClass to false.
boolean includeSuperClass = klass.getClassLoader() != null;
Method[] methods = includeSuperClass ? klass.getMethods() : klass
.getDeclaredMethods();
for (int i = 0; i < methods.length; i += 1) {
try {
Method method = methods[i];
if (Modifier.isPublic(method.getModifiers())) {
String name = method.getName();
String key = "";
if (name.startsWith("get")) {
if ("getClass".equals(name)
|| "getDeclaringClass".equals(name)) {
key = "";
} else {
key = name.substring(3);
}
} else if (name.startsWith("is")) {
key = name.substring(2);
}
if (key.length() > 0
&& Character.isUpperCase(key.charAt(0))
&& method.getParameterTypes().length == 0) {
if (key.length() == 1) {
key = key.toLowerCase();
} else if (!Character.isUpperCase(key.charAt(1))) {
key = key.substring(0, 1).toLowerCase()
+ key.substring(1);
}
Object result = method.invoke(bean, (Object[]) null);
if (result != null) {
this.map.put(key, wrap(result));
}
}
}
} catch (Exception ignore) {
}
}
}
看这上面就知道JSONObject将这个对象通过反射获取字段的名字(当然是通过字段的getter方法,先获取getter方法的名字,然后去除前面的get三个字符,再将第一个字符转小写,对应的就是字段的名字了)和字段的值(通过反射调用getter方法获得value),然后将字段作为key,字段的值作为value存进这个对象本身自带的map集合里面,上面的方法最后会调用到this.map.put(key, wrap(result));这个方法,这个map就是我们熟悉的map集合了,所以我们如果需要过滤掉java对象中某个属性的话,可以在这个地方做手脚,首先新建一个叫做org.json的报名,然后新建一个JSONObject的类,然后将JSONObject的源码复制进去,新建之后的源码树应该是下面这样的:
既然是在有需要的时候过滤,那么就增加一个注解叫做Ignore吧:
package cn.karent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Ignore {
}
然后在private void populateMap(Object bean)
这个方法里面进行注解的判断,如果当前定义的getter方法中有这个注解,那么就忽略掉这个属性,写好之后的代码应该是这样的:
private void populateMap(Object bean) {
Class<?> klass = bean.getClass();
// If klass is a System class then set includeSuperClass to false.
boolean includeSuperClass = klass.getClassLoader() != null;
Method[] methods = includeSuperClass ? klass.getMethods() : klass
.getDeclaredMethods();
for (int i = 0; i < methods.length; i += 1) {
try {
Method method = methods[i];
if( method.isAnnotationPresent(Ignore.class)) {
continue;
}
...此处省略若干代码
} catch (Exception ignore) {
}
}
}
最后放上完整的代码:
private void populateMap(Object bean) {
Class<?> klass = bean.getClass();
// If klass is a System class then set includeSuperClass to false.
boolean includeSuperClass = klass.getClassLoader() != null;
Method[] methods = includeSuperClass ? klass.getMethods() : klass
.getDeclaredMethods();
for (int i = 0; i < methods.length; i += 1) {
try {
Method method = methods[i];
if( method.isAnnotationPresent(Ignore.class)) {
continue;
}
if (Modifier.isPublic(method.getModifiers())) {
String name = method.getName();
String key = "";
if (name.startsWith("get")) {
if ("getClass".equals(name)
|| "getDeclaringClass".equals(name)) {
key = "";
} else {
key = name.substring(3);
}
} else if (name.startsWith("is")) {
key = name.substring(2);
}
if (key.length() > 0
&& Character.isUpperCase(key.charAt(0))
&& method.getParameterTypes().length == 0) {
if (key.length() == 1) {
key = key.toLowerCase();
} else if (!Character.isUpperCase(key.charAt(1))) {
key = key.substring(0, 1).toLowerCase()
+ key.substring(1);
}
Object result = method.invoke(bean, (Object[]) null);
if (result != null) {
this.map.put(key, wrap(result));
}
}
}
} catch (Exception ignore) {
}
}
}
结果
我们在先前定义的address变量上面声明这个Ignore注解:
@Ignore
public String getAddress() {
return address;
}
最后运行看看主程序,看看结果是怎样的:
{"name":"wan","age":10}
源码地址:点我下载