spring cloud feign jackson 枚举json互转 枚举json序列化/反序列化

问题描述

接口返回对象中的一个属性是枚举类型,并且是以json格式输出的,如下:

"status": {
              "name": "NOT_STARTED",
              "desc": "待开始",
              "code": 0
           }

该接口通过前端或者postmain正常调用都没问题,但是。。。内部服务通过feign调用就会出现异常,如下

feign.codec.DecodeException: Error while extracting response for type 
[com.xxxx.cloud.common.response.Result<com.xxxx.omall.marketing.dto.res.MarketingActivityRes>] 
and content type [application/json;charset=UTF-8]; nested exception is org.springframework.
http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize 
instance of `com.xxxx.omall.marketing.dto.enums.FlashPtsStatusEnum` out of START_OBJECT 
token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot deserialize instance of `com.xxxx.omall.marketing.dto.enums.FlashPtsStatusEnum` 
out of START_OBJECT token
at [Source: (ByteArrayInputStream); line: 1, column: 233] (through reference chain: 
com.xxxx.cloud.common.response.Result["data"]->com.xxxx.omall.marketing.dto.res.MarketingActivityRes
["flashPromotions"]->java.util.ArrayList[0]->com.xxxx.omall.marketing.dto.res.FlashPromotionRes["status"])

以下是解决方案

枚举基类

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 
@JsonDeserialize(using = BaseEnumDeserializer.class) 
public interface BaseEnum extends Serializable{
	/**
	 * 调用枚举的this.name()
	 * @return
	 */
	String getCode();
	
	static <E extends Enum<E> & BaseEnum> E valueOf(String enumCode,Class<E> clazz) {
		E enumm = Enum.valueOf(clazz, enumCode);
		return enumm;
	}
	
}

定义自己的枚举并且实现 BaseEnum

import com.fasterxml.jackson.annotation.JsonFormat;
 
/**
 * 通用状态
 * @author xxx
 * 2018年3月26日 上午9:53:51
 */
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum CommonStatus implements BaseEnum{
	CREATE("新建"),
	ENABLED("启用"),
	DISABLED("禁用"),
	DELETE("删除")
	;
	
	private CommonStatus(String displayName) {
		this.displayName = displayName;
	}
	
	private String displayName;
	
	public String getCode(){
		return this.name();
	}
	
	public String getDisplayName() {
		return this.displayName;
	}
 
 
}

自定义枚举转换器

import org.springframework.beans.BeanUtils;
 
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
 
/**
 * 解决 spring cloud json 转枚举问题
 * @author xxxx
 * 2018年6月13日 下午5:30:02
 */
public class BaseEnumDeserializer extends JsonDeserializer<BaseEnum>{
 
	@Override
	@SuppressWarnings("unchecked")
	public BaseEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
		JsonNode node = jp.getCodec().readTree(jp);
		String currentName = jp.currentName();
		Object currentValue = jp.getCurrentValue();
		@SuppressWarnings("rawtypes")
		Class findPropertyType = BeanUtils.findPropertyType(currentName, currentValue.getClass());
		JsonFormat annotation = (JsonFormat) findPropertyType.getAnnotation(JsonFormat.class);
		BaseEnum valueOf;
		if(annotation == null || annotation.shape() != Shape.OBJECT) {
			valueOf = BaseEnum.valueOf(node.asText(), findPropertyType);
		}else {
			valueOf = BaseEnum.valueOf(node.get("code").asText(),findPropertyType);
		}
		return valueOf;
	}
 
 
}

注册转换器

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
 
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.replace_common.mproject.core.enums.BaseEnum;
import com.replace_common.mproject.core.enums.BaseEnumDeserializer;
 
@SpringBootApplication  
@EnableDiscoveryClient  
@EnableCircuitBreaker  
@EnableFeignClients   //启动远程调用,调用其他项目的接口
public class ComputeServiceApplication implements ApplicationListener<ContextRefreshedEvent> {
	
	
	private boolean isExecut;
	
	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if(!isExecut) {
			ApplicationContext applicationContext = event.getApplicationContext();
			//注册转换器
			SimpleModule module = new SimpleModule();
			JsonDeserializer<BaseEnum> deserialize = new BaseEnumDeserializer();
			module.addDeserializer(BaseEnum.class, deserialize);  
			ObjectMapper bean = applicationContext.getBean(ObjectMapper.class);
			bean.registerModule(module);
		}
		isExecut=true;
	}
 
	public static void main(String[] args) {  
		SpringApplication.run(ComputeServiceApplication.class, args);  
	}  
 
}

然后spring cloud feign 内部调用 之间交互的实体类中的枚举就可以自动正常转换了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值