首页 > 技术文章 > FastJson转换自定义枚举类

lyxy 2016-12-17 17:20 原文

在项目中有些状态需要采用枚举类型,在数据库中保存的是name(英文),而前台需要显示的是text(中文)。

所以这就需要自己去实现序列。

例如对象:

import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.annotation.JSONField;

public class Project {
    

    /**
     *
     * 审核状态
     */
    @JSONField(name = "auditStatus")
    private AuditStatus auditStatus;

    
    /**
     *
     * 确认状态
     */
    @JSONField(name = "confirmStatus")
    private ConfirmStatus confirmStatus;

    /**
     * 获取审核状态
     */
    public AuditStatus getAuditStatus() {
        return auditStatus;
    }

    /**
     * 设置审核状态
     */
    public void setAuditStatus(AuditStatus auditingStatus) {
        this.auditStatus = auditStatus ;
    }

    

    /**
     * 获取确认状态
     */
    public ConfirmStatus getConfirmStatus() {
        return confirmStatus;
    }

    /**
     *设置确认状态
     */
    public void setConfirmStatus(ConfirmStatus confirmStatus) {
        this.confirmStatus = confirmStatus;
    }

    

    /**
     * 项目状态
     */
    @JSONField(name = "status")
    private Status status;

    /**
     *获取状态
     */
    public Status getStatus() {
        return status;
    }
    
    /**
     *设置状态
     */
    public void setStatus(Status status) {
        this.status = status;
    }



    /**
     * 状态枚举类
     * 
     * @ClassName: Status
     * @author liwenjian
     * @date 2016年11月11日上午11:33:28
     * @version 1.0.0
     */
    public enum Status {
        beginning("开始"), 
        finished("已结束");

        private String text;

        private Status(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public static Status enumOf(Integer ordinal) {
            for (Status s : Status.values()) {
                if (ordinal == s.ordinal()) {
                    return s;
                }
            }
            return null;
        }

        public static Status enumOf(String name) {
            for (Status s : Status.values()) {
                if (name == s.name() || name.equalsIgnoreCase(s.name())) {
                    return s;
                }
            }
            return null;
        }

        public static String getText(Integer code) {
            Status apf = enumOf(code);
            if (apf != null) {
                return apf.text;
            }
            return null;
        }

        public static String getText(Status status) {
            return status.getText();
        }

    }

    
    /**
     * 审核状态
     * 
     * @ClassName: AuditStatus
     * @author liwenjian
     * @date 2016年11月27日下午2:42:46
     * @version 1.0.0
     */
    public enum AuditStatus {
        /**
         * 待审核
         */
        pending("待审核"),
        /**
         * 已审核
         */
        approve("已审核"),
        /**
         * 已退回
         */
        refuse("已退回"),
        /**
         * 已取消
         */
        cancel("已取消");

        private String text;

        private AuditStatus(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public static AuditStatus enumOf(Integer ordinal) {
            for (AuditStatus as : AuditStatus.values()) {
                if (ordinal == as.ordinal()) {
                    return as;
                }
            }
            return null;
        }

        public static AuditStatus enumOf(String name) {
            for (AuditStatus as : AuditStatus.values()) {
                if (name == as.name() || name.equalsIgnoreCase(as.name())) {
                    return as;
                }
            }
            return null;
        }

        public static String getText(Integer code) {
            AuditStatus as = enumOf(code);
            if (as != null) {
                return as.text;
            }
            return null;
        }

        public static String getText(AuditStatus as) {
            return as.getText();
        }

    }

    /**
     * 
     * 确认状态
     * 
     * @ClassName: ConfirmStatus
     * @author liwenjian
     * @date 2016年11月29日上午11:15:18
     * @version 1.0.0
     */
    public enum ConfirmStatus {
        /**
         * 未确认
         */
        pending("未确认"),
        /**
         * 已确认
         */
        confirmed("已确认");

        private String text;

        private ConfirmStatus(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public static ConfirmStatus enumOf(Integer ordinal) {
            for (ConfirmStatus cs : ConfirmStatus.values()) {
                if (ordinal == cs.ordinal()) {
                    return cs;
                }
            }
            return null;
        }

        public static ConfirmStatus enumOf(String name) {
            for (ConfirmStatus cs : ConfirmStatus.values()) {
                if (name == cs.name() || name.equalsIgnoreCase(cs.name())) {
                    return cs;
                }
            }
            return null;
        }

        public static String getText(Integer code) {
            ConfirmStatus cs = enumOf(code);
            if (cs != null) {
                return cs.text;
            }
            return null;
        }

        public static String getText(ConfirmStatus cs) {
            return cs.getText();
        }

    }

}

数据库保存的状态为:beginning,finished等英文字段

采用JSONObject.toJSONString(project)来转会得到:{"status":"beginning","auditStatus":"pending","confirmStatus":"pending"}

而我的期望是得到:{"status":"开始","auditStatus":"待审核","confirmStatus":"未确认"}

下边就是我自己写的序列工具类:

package cn.com.yodata.core.util;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DecimalFormat;

import com.alibaba.fastjson.serializer.DoubleSerializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;

import com.lwj.modules.project.model.Project;
import com.lwj.modules.project.model.SubProject;

/**
 * JSON序列
 * 
 * @ClassName: SerializeUtil
 * @author liwenjian
 * @date 2016年12月15日下午6:15:14
 * @version 1.0.0
 */
public class SerializeUtil {
    private static SerializeConfig globalInstance = SerializeConfig.getGlobalInstance();
    static {
        // 配置需要序列的指定类
        globalInstance.put(Double.class, new DoubleSerializerConfig(new DecimalFormat("0.00")));
        globalInstance.put(Project.Status.class, EnumStatusSerializer.instance);
        globalInstance.put(Project.AuditStatus.class, EnumStatusSerializer.instance);
        globalInstance.put(Project.ConfirmStatus.class, EnumStatusSerializer.instance);
        globalInstance.put(SubProject.Status.class, EnumStatusSerializer.instance);
        globalInstance.put(SubProject.AuditStatus.class, EnumStatusSerializer.instance);
    }

    public static SerializeConfig instance() {
        return globalInstance;
    }

    /**
     * Double格式保留两位小数点(0.00)
     * 
     * @ClassName: DoubleSerializerConfig
     * @author liwenjian
     * @date 2016年12月17日下午3:09:43
     * @version 1.0.0
     */
    public static class DoubleSerializerConfig extends DoubleSerializer {
        public DoubleSerializerConfig(DecimalFormat decimalFormat) {
            this.decimalFormat = decimalFormat;
        }

        private DecimalFormat decimalFormat = null;

        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                throws IOException {
            SerializeWriter out = serializer.out;

            if (object == null) {
                out.writeNull(SerializerFeature.WriteNullNumberAsZero);
                return;
            }

            double doubleValue = ((Double) object).doubleValue();

            if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) {
                out.writeNull();
            } else {
                if (decimalFormat == null) {
                    out.writeDouble(doubleValue, true);
                } else {
                    String doubleText = decimalFormat.format(doubleValue);
                    out.write("\"" + doubleText + "\"");
                }
            }
        }
    }

    /**
     * 枚举类序列
     * 
     * @ClassName: EnumStatusSerializer
     * @author liwenjian
     * @date 2017年2月23日上午11:13:50
     * @version 1.0.0
     */
    public static class EnumStatusSerializer implements ObjectSerializer {
        
        public final static EnumStatusSerializer instance = new EnumStatusSerializer();

        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                throws IOException {
            SerializeWriter out = serializer.out;
            if (object instanceof Project.Status) {
                // 总项目状态
                Project.Status status = (Project.Status) object;
                // 如果直接使用out.write(status.getText()),则输出的值没有双引号,json格式不对,所以这里前后加了双引号
                out.write("\"" + status.getText() + "\"");
            } else if (object instanceof Project.AuditStatus) {
                // 总项目审核状态
                Project.AuditStatus status = (Project.AuditStatus) object;
                out.write("\"" + status.getText() + "\"");
            } else if (object instanceof Project.ConfirmStatus) {
                // 总项目确认状态
                Project.ConfirmStatus status = (Project.ConfirmStatus) object;
                out.write("\"" + status.getText() + "\"");
            } else if (object instanceof SubProject.Status) {
                SubProject.Status status = (SubProject.Status) object;
                out.write("\"" + status.getText() + "\"");
            } else if (object instanceof SubProject.AuditStatus) {
                SubProject.AuditStatus status = (SubProject.AuditStatus) object;
                out.write("\"" + status.getText() + "\"");
            } else {
                out.writeEnum((Enum<?>) object);
            }
        }

    }

}

 

转换的时候需要加入自己指定的SerializeConfig。

JSONObject.toJSONString(project,SerializeUtil.instance());

上面SerializeUtil序列工具类主要实现了ObjectSerializer序列化器,并实现接口write(),然后自己实现write方法组合自己需要的值。

ObjectSerializer中原码如下:

/*
 * Copyright 1999-2101 Alibaba Group.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.fastjson.serializer;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * Interface representing a custom serializer for fastjson. You should write a custom serializer, if
 * you are not happy with the default serialization done by fastjson. You will also need to register
 * this serializer through {@link com.alibaba.fastjson.serializer.SerializeConfig#put(Type, ObjectSerializer)}.
 *
 * <pre>
 * public static class Result {
 *     public ResultCode code;
 * }
 * 
 * public static enum ResultCode {
 *     LOGIN_FAILURE(8), INVALID_ARGUMENT(0), SIGN_ERROR(17);
 *     public final int value;
 *     ResultCode(int value){
 *         this.value = value;
 *     }
 * }
 * 
 * public static class ResultCodeSerilaizer implements ObjectSerializer {
 *     public void write(JSONSerializer serializer, 
 *                       Object object, 
 *                       Object fieldName, 
 *                       Type fieldType,
 *                       int features) throws IOException {
 *         serializer.write(((ResultCode) object).value);
 *     }
 * }
 * 
 * SerializeConfig.getGlobalInstance().put(ResultCode.class, new ResultCodeSerilaizer());
 * 
 * Result result = new Result();
 * result.code = ResultCode.SIGN_ERROR;
 * String json = JSON.toJSONString(result, config); // {"code":17}
 * Assert.assertEquals("{\"code\":17}", json);
 * </pre>
 * @author wenshao[szujobs@hotmail.com]
 */
public interface ObjectSerializer {
    
    /**
     * fastjson invokes this call-back method during serialization when it encounters a field of the
     * specified type.
     * @param serializer 
     * @param object src the object that needs to be converted to Json.
     * @param fieldName parent object field name
     * @param fieldType parent object field type
     * @param features parent object field serializer features
     * @throws IOException
     */
    void write(JSONSerializer serializer, //
               Object object, //
               Object fieldName, //
               Type fieldType, //
               int features) throws IOException;
}

 

SerializeUtil工具类实现后的方法:

public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                throws IOException {
            SerializeWriter out = serializer.out;
            if (object instanceof Project.Status) {
                // 总项目状态
                Project.Status status = (Project.Status) object;
          //注意
          //如果直接使用out.write(status.getText()),则输出的值没有双引号,json格式不对,所以这里前后加了双引号
out.write(
"\"" + status.getText() + "\""); } else if (object instanceof Project.AuditStatus) { // 总项目审核状态 Project.AuditStatus status = (Project.AuditStatus) object; out.write("\"" + status.getText() + "\""); } else if (object instanceof Project.ConfirmStatus) { // 总项目确认状态 Project.ConfirmStatus status = (Project.ConfirmStatus) object; out.write("\"" + status.getText() + "\""); } else if (object instanceof SubProject.Status) { SubProject.Status status = (SubProject.Status) object; out.write("\"" + status.getText() + "\""); } else if (object instanceof SubProject.AuditStatus) { SubProject.AuditStatus status = (SubProject.AuditStatus) object; out.write("\"" + status.getText() + "\""); } else { out.writeEnum((Enum<?>) object); } }

 

推荐阅读