栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 反序列化的自定义表达式解析实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 反序列化的自定义表达式解析实现

简介:

       通过SPEL 和 fastjson 配合使用,指定JSON中字段解析的表达式,实现指定字段按照指定表达式填充的效果。

       以使用三目运算符指定解析为例,代码如下。

首先,定义字段的反序列化解析类 SpelExpressDeserializer

import java.lang.reflect.Type;

import org.springframework.expression.expression;
import org.springframework.expression.expressionParser;
import org.springframework.expression.spel.standard.SpelexpressionParser;
import org.springframework.expression.spel.support.StandardevaluationContext;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.deserializer.ContextObjectDeserializer;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;

import lombok.extern.slf4j.Slf4j;


@Slf4j
public class SpelExpressDeserializer extends ContextObjectDeserializer implements ObjectDeserializer {

	private expressionParser spel = new SpelexpressionParser();

	@Override
	public int getFastMatchToken() {
		return 0;
	}

	@SuppressWarnings("unchecked")
	@Override
	public  T deserialze(DefaultJSonParser parser, Type type, Object fieldName, String format, int features) {
		Object parse = parser.parse(fieldName);
		if (null == parse || StringUtils.isEmpty(format)) {
			return null;
		}

		// 通过SPEL运算出结果。
		StandardevaluationContext context = new StandardevaluationContext();
		context.setVariables(JSON.parseObject(parser.getInput()));
		T value = null;
		try {
			String express = format.replaceAll("'", """);
			expression exp = spel.parseexpression(express);
			value = (T) exp.getValue(context, type.getTypeName());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return value;
	}

}

然后,单元测试如下

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.junit.Test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;

import lombok.Data;

public class JsonFormatWithSpelTest {

	@Data
	static class DemoBill {

		
		private String billNo;
		
		private String remark;
		
		@JSonField(alternateNames = "remark", format = "#remark == null || #remark.isEmpty()? false:true", deserializeUsing = SpelExpressDeserializer.class)
		private Boolean has_remark;
		
		@JSonField(alternateNames = "remark", format = "#remark == null || #remark.isEmpty()? 0:#remark.length()", deserializeUsing = SpelExpressDeserializer.class)
		private Integer remark_length;

	}

	@Test
	public void testDeserializer() {

		String json_a = "{"billNo":"No0001","remark":"1234","_remark":"1234"}";
		DemoBill demo_a = fillJson(json_a, DemoBill.class);
		System.out.println("demo_a: " + JSON.toJSonString(demo_a));

		String json_b = "{"billNo":"No0002"}";
		DemoBill demo_b = fillJson(json_b, DemoBill.class);
		System.out.println("demo_b: " + JSON.toJSonString(demo_b));
	}

	
	private  T fillJson(String sourceJson, Class clazz) {
		Map> fieldMap = getNameMapping(clazz);
		JSonObject json = JSON.parseObject(sourceJson);
		// 填充自定义标签字段值,用关联字段填充,因为JSON数据中不包含当前属性时,反序列化方法不会执行。
		for (Entry> entry : fieldMap.entrySet()) {
			String key = entry.getKey();
			Object val = json.containsKey(key) ? json.get(entry.getKey()) : "";
			entry.getValue().forEach(a -> json.put(a, val));
		}
		return JSON.parseObject(json.toJSonString(), clazz);
	}

	
	private Map> getNameMapping(Class clazz) {
		Map> fieldMap = new HashMap<>();
		Field[] declaredFields = clazz.getDeclaredFields();
		for (Field declaredField : declaredFields) {
			declaredField.isAnnotationPresent(JSONField.class);
			JSonField annotation = declaredField.getAnnotation(JSONField.class);
			if (null == annotation) {
				continue;
			}
			if (annotation.deserializeUsing().equals(SpelExpressDeserializer.class)) {
				String name = declaredField.getName();
				String refField = annotation.alternateNames()[0];
				List list = fieldMap.get(refField);
				if (null == list) {
					list = new ArrayList<>();
				}
				list.add(name);
				fieldMap.put(refField, list);
			}
		}
		return fieldMap;
	}

}

说明:JSON字符串中不包含某个属性时,不会进入反序列化方法

打印结果如下。

demo_a: {"billNo":"No0001","has_remark":true,"remark":"1234","remark_length":4}
demo_b: {"billNo":"No0002","has_remark":false,"remark_length":0}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/630814.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号