java Class类对象转换为json字符串(为对象初始化默认值)

起因

自己在写接口文档或者进行postman测试时,需要一些json字符串来作为接口入参或者返回值,以前都是要手动地创建一个对象,并对属性赋值后再通过阿里的fastjson输出的,挺麻烦的,后面想了想能不能只需要Class类就能够产生json字符串,之前也在swagger2的一个ui中看到了类似的效果。但我现在是想自动地生成postman的导入需要的json文件,所以需要自定义注解后,再获取注解标注的参数或方法的返回值的Class类对象,这时候就是搞这个的动机——要将Class类对象转为json字符串

过程

其实关键是为类反射创建的对象的属性赋初始值。
只不过这里属性的类分情况:

  1. 基本数据类型:例如int初值是0,boolean初值是false,赋初值jvm都帮我们搞定了,就不用我们处理了。
  2. 包装类以及系统的一些常用类型:如Integer,String,Date,这些就需要我们手动进行赋初值了。
  3. 自定义的类型:这个在我的应用中,一般是vo层的实体类,我们处理时就需要递归到第1种和第2种为止,然后它们的定义我是判断该类的package是否是以项目的package开始的,即利用String的startsWith方法
  4. 集合类型:我这里只考虑了List(因为其他的用得少,大家可以自行加上),这里关键是获得List的泛型从而对其进行分情况,所以也要求类中的List属性要加上泛型。

我主要是参照了这个链接里的这个链接里的

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

public class ClassInitUtils {

    private static final String PROJECT_BASE_PACKAGE = "自己项目的包名";

    public static <T> T getObjDefault(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        T instance = clazz.newInstance();
        Field[] fs = clazz.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];

            // 设置些属性是可以访问的
            boolean isStatic = Modifier.isStatic(f.getModifiers());
            if (isStatic) {
                continue;
            }
            // 设置些属性是可以访问的
            f.setAccessible(true);
            try {
                Class<?> type = f.getType();
                //是基本数据类型
                if (type.isPrimitive())
                    continue;
                // 得到此属性的值
                Object val = f.get(instance);
                // 得到此属性的类型
                String typeStr = type.toString();
                if (typeStr.endsWith("String") && val == null) {
                    f.set(instance, "");
                } else if ((typeStr.endsWith("Integer") || typeStr.endsWith("Double")) && val == null) {
                    f.set(instance, 0);
                } else if ( typeStr.endsWith("Long") && val == null) {
                    f.set(instance, 0L);
                } else if (typeStr.endsWith("Date") && val == null) {
                    f.set(instance, Date.valueOf("1970-01-01"));
                } else if (typeStr.endsWith("Timestamp") && val == null) {
                    f.set(instance, Timestamp.valueOf("1970-01-01 00:00:00"));
                } else if (typeStr.endsWith("BigDecimal") && val == null) {
                    f.set(instance, new BigDecimal(0));
                } else if (type.getPackage().toString().startsWith(PROJECT_BASE_PACKAGE)) {
                    f.set(instance, getObjDefault(type));
                } else if (type.isAssignableFrom(List.class)) {
                    f.set(instance,getObjDefaultList(f));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return instance;
    }

    public static List<Object>getObjDefaultList(Field field) throws IllegalAccessException, InstantiationException {
    	//获取List的泛型
        Type genericType = field.getGenericType();
        List<Object>list=new ArrayList();
        //无泛型
        if (null == genericType) {
            return list;
        }
        if (genericType instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) genericType;
            // 得到泛型里的class类型对象
            Class<?> actualTypeArgument = (Class<?>) pt.getActualTypeArguments()[0];
            Object obj = getObjDefault(actualTypeArgument);
            //List属性默认只填入一个
            list.add(obj);
        }
        return list;
    }
}

我上方的代码逻辑也挺明了的,目前在我的项目中挺适用的,能够应对常用的属性。我也看到了上面代码的getObjDefault和getObjDefaultList存在着相互递归调用的情况,可能会导致栈溢出,大家可以结合自身的情况进行改进。

剩下步骤的就简单了,直接利用阿里的fastjson将对象转为json串即可
(不过fastjson会将类中的属性按字典序排序,json串里的属性就不是原来的顺序了,有些别扭)

Object obj = ClassInitUtils.getObjDefault(type);
String raw = JSONObject.toJSONString(obj);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值