JSONObject增加过滤注解

前言

最近在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}

演示地主
源码地址:点我下载

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值