fastjson反序列化formate时间等特殊格式处理,@JSONField的name属性首字母为大转JSON后变小写处理

背景

今天在实际编码过程中碰到一个问题,需要将实体格式化转为JSON,然后再将JSON反序列化为数据库对象存储到数据库中。@JSONField注解用的不亦乐乎,然后测试的时候悲剧了,JSON换格式要求为“yyyyMMddHHmmss”,那么果断“@JSONField(name = “xxxxxxx”, format = “yyyyMMddHHmmss”)”。当将转换的JSON对方反序列化发现时间格式字段无法反序列化并报错。网上各种找资料发现阿里的fastjson反序列化并不支持format。心里一万头草泥马奔过。没办法别人不提供咱自己弄吧(网上的感觉都不那么靠谱),亲测有效,如有性能等高要求的请略过。

注如果需要实现多级嵌套实体JSON间转换,请自行改造递归,此处不提供

序第二个问题当@JSONField的name属性首字母为大写,同时实体使用lombok的@data、@get、@set(不愿意写get、set,也就是@JSONField直接写在属性上而不是写在get方法上)测试转换为JSON对象时首字母变小写了。

干货-代码

问题一代码

public static  T JosnToObject(String json, Class clazz) {
        JSONObject jsonObject = JSON.parseObject(json);
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            Object objValue = jsonObject.get(fieldName);
            if (objValue != null) {
                //如果是日期类型
                if (field.getGenericType().getTypeName().equals("java.sql.Timestamp")) {
                    JSONField jsonField = field.getAnnotation(JSONField.class);
                    if (jsonField != null) {
                        String formtStr = jsonField.format();
                        String nowVal = objValue.toString();
                        switch (formtStr) {
                            case "yyyyMMddHHmmss":
                                if (nowVal.length() == nowVal.length()) {
                                    nowVal = nowVal.substring(0, 4)
                                            + "-" + nowVal.substring(4, 6)
                                            + "-" + nowVal.substring(6, 8)
                                            + " " + nowVal.substring(8, 10)
                                            + ":" + nowVal.substring(10, 12)
                                            + ":" + nowVal.substring(12, 14);
                                }
                                break;
                            case "yyyyMMdd":
                                if (nowVal.length() == nowVal.length()) {
                                    nowVal = nowVal.substring(0, 4)
                                            + "-" + nowVal.substring(4, 6)
                                            + "-" + nowVal.substring(6, 8)
                                            + " 00:00:00";
                                }
                                break;
                            default:
                                break;
                        }

                        jsonObject.put(fieldName, Timestamp.valueOf(nowVal));
                    }
                }
            }
        }
        return JSONObject.toJavaObject(jsonObject, clazz);
    }

问题二代码

/**
     * json 序列化
     * @return
     */
    public static  String objToJson(T obj,Class clazz){
        // 输出的JSON对象
        JSONObject newObj = new JSONObject();
        // 输入的JSON对象
        JSONObject jsonObj = (JSONObject) JSON.toJSON(obj);
        for(String key : jsonObj.keySet()){
            for(Field field : clazz.getDeclaredFields()){
                if(field.getName().toLowerCase().equals(key.toLowerCase())){
                    // 获取字段注解内容
                    JSONField annotation = field.getAnnotation(JSONField.class);
                    Object o = jsonObj.get(key);
                    if(o != null){
                        // 重新封装JSON对象
                        newObj.put(annotation.name(),o);
                    }
                }
            }
        }
        return newObj.toJSONString();
    }

原理

  • 问题一
    • 将JSON转换为JSONObject对象
    • 获取转换后实体所有属性
    • 遍历实体属性
    • 获取属性上JSONField注解对象
    • 检测到format属性为需要重新格式化时
    • 原值格式化为正确格式类型(源码只提供了时间格式,其他格式自行添加不赘述)
    • 修改JSONObject对象中对应属性值为格式化后的值
    • 调用JSONObject.toJavaObject转为实体返回
  • 问题二
    • 创建输出JSONObject对象
    • json反序列化输入JSONObject对象
    • 嵌套循环输入JSONObject对象与实体属性集合
    • 名称转小写比对一致则替换
    • 调用JSONObject.toJavaObject转为实体返回

你可能感兴趣的:(JSON,Java,Spring)