FastJson转换自定义枚举类
在项目中有些状态需要采用枚举类型,在数据库中保存的是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); } }