非标准映射的json数据, 通过反射的方式映射到实体类

场景描述

一个三方合作的项目,对某工厂的产线生产情况进行大屏监控, 产线数据流转流程
产线采数 —> 数据解析 ----> 大屏展示
我们处于数据解析的环节, 有产线现场mes采数推送给我们, 然后我们解析完毕之后再推送给另一家公司进行大屏展示.

数据格式与实体类模板

mes采集的数据格式, 是一串标准的json格式, 但是json中的key 与实体类中的属性是不对应的

{"A01": 5032 ,"A02": 4811 ,"A03": 4905 ,"A04": 5449 ,"A05": 9164 ,"A06": 8385 ,
"A07": 779  ,"A08": 7    ,"A09": 91   ,"A10": 21   ,"A11": 15 ,"A12": 0  ,"A13": 0,
"A14": 110  ,"A15": 365  ,"A16": 43   ,"A17": 58   ,"A18": 6 ,"A19": 14 ,"A20": 40 ,
"A21": 9 ,"A22":-2147483647. ,"A23": 10031,"A24": 9357 ,"A25": 674  ,"A26": 138 ,
"A27": 90 ,"A28": 0    ,"A29": 32   ,"A30": 5    ,"A31": 0  ,"A32": 121  ,"A33": 118,
"A34": 73   ,"A35": 23   ,"A36": 17   ,"A37": 22   ,"A38": 26   ,"A39": 0    ,
"A40": 0.000000000 }	

实体类结构
类字段很多, 并且有很多各类
在这里插入图片描述

不使用反射 进行数据解析

数据采集方法
mes数据的采集是采用的mqtt消息队列
这里只展示数据解析的过程, 不展示mqtt相关的代码

public void handleMessage(Message<?> message) throws MessagingException {
		String topic = (String) message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC);
		log.info("----------------------");
		log.info("接收到了消息");
		log.info("message: {}",message);
		log.info("payload: {}",message.getPayload());
		log.info("PacketId: {}",message.getHeaders().getId());
		log.info("Qos: {}",message.getHeaders().get(MqttHeaders.QOS));
		log.info("topic: {}",topic);

		
		MesDataEntity mesData = new MesDataEntity();
		mesData.setMessage(message.toString());
		Object payload = message.getPayload();
		if (payload != null) {
			mesData.setPayload(payload.toString());
		}
		UUID id = message.getHeaders().getId();
		if (id != null) {
			mesData.setPacketId(id.toString());
		}
		Object o = message.getHeaders().get(MqttHeaders.QOS);
		if (o != null) {
			mesData.setQos(o.toString());
		}
		
		// 从mqtt取到核心的消息体
		String data = payload.toString();
		// 数据推送的方法
		Boolean aBoolean = httpData(data);


		/****** 其他的业务处理********/
		/**.
		.
		.
		.
		.
		./
		

    }

数据推送方法

	public Boolean httpData(String data){
		// 数据解析
		List<JSONObject> jsonObject = analyseData(data);
		// 推送数据
		HttpResponse responsse = HttpRequest.post(url)
				.header("Content-Type","application/json;charset=UTF-8")
				.body(jsonObject.toString())
				.timeout(2)
				.execute();
		String body = responsse.body();
		JSONObject responsseJson = JSONObject.parseObject(body);
		Boolean success = (boolean)responsseJson.get("success");
		return success;
	}

数据解析方法

	/**
	 * 解析数据
	 * @param data
	 * @return
	 */
	public List<JSONObject> analyseData(String data){
		List<JSONObject> res = null;
		JSONObject source= JSON.parseObject(data);
		String time = source.get("time").toString();
		String id = source.get("id").toString();
		EquipmentEnum enumByValue = EquipmentEnum.getEnumByValue(id);
		switch (enumByValue){
			case ID_0001: { res = mappingMes13Dto0001(source.get("data").toString(),time);break;}
			case ID_0047: { res = mappingMes13Dto0047(source.get("data").toString(),time);break;}
			default: break;
		}

		return res;
	}


	public List<JSONObject> mappingMes13Dto0001(String json,String time){
		List<JSONObject> res = new ArrayList<>();
		Mes13Dto0001 mes13Dto0001 = JSONObject.parseObject(json, Mes13Dto0001.class);

		// 01冷端实体封装
		JSONObject jsonObject = mappingLengDJC01(mes13Dto0001,time);
		// 02冷端实体封装
		JSONObject lengDJC02 = mappingLengDJC02(mes13Dto0001,time);

		// 上管机实体封装
		JSONObject jsonObject1 = mappingShangGJ(mes13Dto0001, time);

		JSONObject jsonObject2 = mappingReDJC(mes13Dto0001, time);
		res.add(jsonObject);
		return res;
	}

/** 像这样不用反射, 需要再每一个实体封装的方法里面全部手动set一遍,
这里我只列举了两个实体类, 实际项目中有22个实体类需要去设置
尤其是如果涉及到共用字段的话 代码重复量太大了
*/
	/**
	 * 冷端检测01
	 * @param mes13Dto0001
	 * @return
	 */
	public JSONObject mappingLengDJC01(Mes13Dto0001 mes13Dto0001,String time){
		JSONObject json_1 = new JSONObject();
		LengDJC lengDJC = new LengDJC();
		lengDJC.setPower(mes13Dto0001.getA01().toString());
		lengDJC.setFaultSignal(mes13Dto0001.getA02().toString());
		lengDJC.setPingJiShu(mes13Dto0001.getA03().toString());
		lengDJC.setSheBeiHao(mes13Dto0001.getA04().toString());
		/**
		 * .
		 * .
		 * .
		 * .
		 * .
		 * .
		 */
		json_1.put("time",DateUtil.getLong(time,timeFormat));
		json_1.put("deviceName",EquipmentEnum.LDJC_01.getValue());
		json_1.put("data",lengDJC);
		return json_1;
	}
/**
	 * 冷端检测02
	 * @param mes13Dto0001
	 * @return
	 */
	public JSONObject mappingLengDJC02(Mes13Dto0001 mes13Dto0001,String time){
		JSONObject json_1 = new JSONObject();
		LengDJC lengDJC = new LengDJC();
		lengDJC.setPower(mes13Dto0001.getA10().toString());
		lengDJC.setFaultSignal(mes13Dto0001.getA11().toString());
		lengDJC.setPingJiShu(mes13Dto0001.getA12().toString());
		lengDJC.setSheBeiHao(mes13Dto0001.getA13().toString());
		/**
		 * .
		 * .
		 * .
		 * .
		 * .
		 */
		json_1.put("time",DateUtil.getLong(time,timeFormat));
		json_1.put("deviceName",EquipmentEnum.LDJC_02.getValue());
		json_1.put("data",lengDJC);
		return json_1;
	}
 /**** 一直往下再写七八个类似的封装方法 ******/
 

使用反射的方式

数据采集和数据推送方法没有变化
主要变化的是实体类封装的过程

首先需要新建立一个映射类
这里可以选择以元数据作为key 只初始化一个所有映射的集合

也可以选择以实体类属性作为key, 初始化每个类对应的hash映射
这里针对我的应用场景,考虑到解析映射是效率的问题, 我选择了第二种,建立每一个实体类的hash映射

public class MapRelation {
    private static final Map<String,String> all;
    private static final Map<String,String> lengDJC01;
    static{
        // 以元数据作为key
        Map<String,String> map = new HashMap<>();
        map.put("A01","");
        /**
         * 填入每一个的映射
         * .
         * .
         * .
         */
        all = Collections.unmodifiableMap(map);
    }
    static{
        // 以实体类属性作为key
        Map<String,String> map = new HashMap<>();
        map.put("power","");
        /**
         * 填入每一个的映射
         * .
         * .
         * .
         */
        lengDJC01 = Collections.unmodifiableMap(map);
    }
}

最终的实体映射类

public class MapRelation {
    private static final Map<String,String> lengDJC01;
    private static final Map<String,String> lengDJC02;
    private static final Map<String,String> shangGJ01;
    private static final Map<String,String> shangGJ02;
    private static final Map<String,String> shangGJ03;
    private static final Map<String,String> shangGJ04;
    private static final Map<String,String> tuiHL;
    private static final Map<String,String> zhuangHJ01;
    private static final Map<String,String> zhuangHJ02;
    private static final Map<String,String> dianB01;
    private static final Map<String,String> reDJC01;
    private static final Map<String,String> reDJC02;
    private static final Map<String,String> reDJC03;
    private static final Map<String,String> reDJC04;

    // lengDJC01 映射
    static{
        Map<String,String> map = new HashMap<>();
        map.put("power","A01");
        map.put("faultSignal","A02");
        // 其他字段省略
        lengDJC01 = Collections.unmodifiableMap(map);
    }
    // lengDJC02 映射
    static{
        Map<String,String> map = new HashMap<>();
        map.put("power","A03");
        map.put("faultSignal","A04");
        // 其他字段省略
        lengDJC02 = Collections.unmodifiableMap(map);
    }
    // shangGJ01 映射
    static{
        Map<String,String> map = new HashMap<>();
        map.put("power","A05");
        map.put("faultSignal","A06");
        map.put("gongZuoGenShu","A07");
        map.put("meiBanGenShu","A08");
        map.put("liaoCangGenSHu","A09");
        map.put("guanNeiGenShu","A10");
        shangGJ01 = Collections.unmodifiableMap(map);
    }
    // shangGJ02 映射
    static{
        Map<String,String> map = new HashMap<>();
        map.put("power","A11");
        map.put("faultSignal","A12");
 		// 其他字段省略
        shangGJ02 = Collections.unmodifiableMap(map);
    }
    // shangGJ03 映射
    static{
        Map<String,String> map = new HashMap<>();
        // 映射省略
        shangGJ03 = Collections.unmodifiableMap(map);
    }
    // shangGJ04 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        shangGJ04 = Collections.unmodifiableMap(map);
    }
    // zhuangHJ01 映射
    static{
        Map<String,String> map = new HashMap<>();
          // 映射省略
        zhuangHJ01 = Collections.unmodifiableMap(map);
    }
    // zhuangHJ02 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        zhuangHJ02 = Collections.unmodifiableMap(map);
    }
    // reDJC01 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        reDJC01 = Collections.unmodifiableMap(map);
    }
    // reDJC02 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        reDJC02 = Collections.unmodifiableMap(map);
    }
    // reDJC03 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        reDJC03 = Collections.unmodifiableMap(map);
    }
    // reDJC04 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        reDJC04 = Collections.unmodifiableMap(map);
    }
    // tuiHL 映射
    static{
        Map<String,String> map = new HashMap<>();
           // 映射省略
        tuiHL = Collections.unmodifiableMap(map);
    }
    // dianB01 映射
    static{
        Map<String,String> map = new HashMap<>();
          // 映射省略
        dianB01 = Collections.unmodifiableMap(map);
    }
}

有的同学可能看到上面映射会有点疑问, 这样和创建实体类有什么区别呢, 创建实体类也要每一个方法里面都set, 这样只不过是把set转换成了map呀
那接下来我们来看一下实体类解析的方法, 如果不使用反射映射, 那么有多少个实体类就要写多少个方法
比如上面我们写了14个map映射, 那么久对应着14个实体类封装的方法

如果使用反射的话, 那么我们只需要一个方法就能搞定

	/**
	 * 对象解析封装
	 * @param obj 元数据对象
	 * @param time 上报时间
	 * @param deviceName 设备名称
	 * @param tClass 目标对象class
	 * @param mapRelation 对象映射关系
	 * @param <T>
	 * @return
	 */
	public <T> JSONObject mappingData(Object obj,String time,String deviceName,Class<T> tClass,Map<String,String> mapRelation){
		// 获取目标对象的属性
		Field[] declaredFields = tClass.getDeclaredFields();
		Object o = null;
		String value = "";
		try{
			// 获取目标对象的实例化对象
			o = tClass.newInstance();
			for (Field declaredField : declaredFields) {
				//设置属性可操作
				declaredField.setAccessible(true);
				//获取属性名称
				String name = declaredField.getName();
				//通过属性名称去hash映射中 获取对应的元数据key
				value = mapRelation.get(name);
				if (StringUtils.isBlank(value)) {
					continue;
				}
				// 通过属性名称 获取元数据的属性
				Field field = obj.getClass().getDeclaredField(value);
				// 获取元数据的实例化对象
				// 设置属性可操作
				field.setAccessible(true);
				// field.get(mes13Dto0001).toString() 获取元数据的属性值
				// 给目标对象属性赋值
				declaredField.set(o,field.get(obj).toString());
			}
		}catch (NoSuchFieldException e) {
			log.info("字段解析异常,对象 {} 不包含该字段,{}",obj,value);
		} catch (InstantiationException e) {
			e.printStackTrace();
			log.info("目标对象实例化异常 {}",tClass);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			log.info("元数据属性获取异常, 元数据{}, 属性{}",obj,value);
		}
		// 封装推送数据
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("time",DateUtil.getLong(time,timeFormat));
		jsonObject.put("deviceName",deviceName);
		jsonObject.put("data",o);
		return jsonObject;
	}

最终成型代码

映射类省略 参照上述最终的实体映射类

数据解析类

public class MqttMessageHandle implements MessageHandler {
	@Autowired
	IMesDataService mesDataService;

	@Value("unicom.url")
	String url;

	private String timeFormat = "yyyy-MM-dd HH:mm:ss";
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
		String topic = (String) message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC);
		log.info("----------------------");
		log.info("接收到了消息");
		log.info("message: {}",message);
		log.info("payload: {}",message.getPayload());
		log.info("PacketId: {}",message.getHeaders().getId());
		log.info("Qos: {}",message.getHeaders().get(MqttHeaders.QOS));
		log.info("topic: {}",topic);

		Object payload = message.getPayload();
		// 数据推送
		String data = payload.toString();
		boolean aBoolean = httpData(data);

		// 元数据封装入库
		MesDataEntity mesData = new MesDataEntity();
		mesData.setMessage(message.toString());
		if (payload != null) {
			mesData.setPayload(payload.toString());
		}
		UUID id = message.getHeaders().getId();
		if (id != null) {
			mesData.setPacketId(id.toString());
		}
		Object o = message.getHeaders().get(MqttHeaders.QOS);
		if (o != null) {
			mesData.setQos(o.toString());
		}

		// 是否推送成功
		Integer ispush = aBoolean ? 1:0;
		mesData.setIspush(ispush);
		mesData.setTopic(topic);
		mesData.setCreateTime(new Date());
		mesDataService.insert(mesData);
    }

	/**
	 * 推送消息
	 * @param data
	 * @return
	 */
	public Boolean httpData(String data){
		// 数据解析
		List<JSONObject> jsonObject = analyseData(data);
		// 推送数据
		HttpResponse responsse = HttpRequest.post(url)
				.header("Content-Type","application/json;charset=UTF-8")
				.body(jsonObject.toString())
				.timeout(2)
				.execute();
		String body = responsse.body();
		JSONObject responsseJson = JSONObject.parseObject(body);
		Boolean success = (boolean)responsseJson.get("success");
		return success;
	}

	/**
	 * 解析数据
	 * @param data
	 * @return
	 */
	public List<JSONObject> analyseData(String data){
		List<JSONObject> res = null;
		JSONObject source= JSON.parseObject(data);
		String time = source.get("time").toString();
		String id = source.get("id").toString();
		EquipmentEnum enumByValue = EquipmentEnum.getEnumByValue(id);
		switch (enumByValue){
			case ID_0001: { res = mappingMes13Dto0001(source.get("data").toString(),time);break;}
			case ID_0047: { res = mappingMes13Dto0047(source.get("data").toString(),time);break;}
			default: break;
		}

		return res;
	}

	/**
	 * 0001 盒子数据
	 * @param json
	 * @param time
	 * @return
	 */
	public List<JSONObject> mappingMes13Dto0001(String json,String time){
		List<JSONObject> res = new ArrayList<>();
		Mes13Dto0001 mes13Dto0001 = JSONObject.parseObject(json, Mes13Dto0001.class);

		// 01冷端实体封装
		JSONObject lengDJC01 = mappingData(mes13Dto0001, time, EquipmentEnum.LDJC_01.getValue(), LengDJC.class, MapRelation.lengDJC01);
		// 02冷端实体封装
		JSONObject lengDJC02 = mappingData(mes13Dto0001, time, EquipmentEnum.LDJC_02.getValue(), LengDJC.class, MapRelation.lengDJC02);
		// 上管机01实体封装
		JSONObject shangGJ01 = mappingData(mes13Dto0001, time, EquipmentEnum.SGJ_01.getValue(), ShangGJ.class, MapRelation.shangGJ01);
		// 上管机02实体封装
		JSONObject shangGJ02 = mappingData(mes13Dto0001, time, EquipmentEnum.SGJ_02.getValue(), ShangGJ.class, MapRelation.shangGJ02);
		// 上管机03实体封装
		JSONObject shangGJ03 = mappingData(mes13Dto0001, time, EquipmentEnum.SGJ_03.getValue(), ShangGJ.class, MapRelation.shangGJ03);
		// 上管机04实体封装
		JSONObject shangGJ04 = mappingData(mes13Dto0001, time, EquipmentEnum.SGJ_04.getValue(), ShangGJ.class, MapRelation.shangGJ04);

		res.add(lengDJC01);
		res.add(lengDJC02);
		res.add(shangGJ01);
		res.add(shangGJ02);
		res.add(shangGJ03);
		res.add(shangGJ04);
		return res;
	}
	/**
	 * 0047 盒子数据
	 * @param json
	 * @param time
	 * @return
	 */
	public List<JSONObject> mappingMes13Dto0047(String json,String time){
		List<JSONObject> res = new ArrayList<>();
		Mes13Dto0047 mes13Dto0047 = JSONObject.parseObject(json, Mes13Dto0047.class);
		// 01热端实体封装
		JSONObject reDJC01 = mappingData(mes13Dto0047, time, EquipmentEnum.RQB_01.getValue(), ReDJC.class, MapRelation.reDJC01);
		// 02热端实体封装
		JSONObject reDJC02 = mappingData(mes13Dto0047, time, EquipmentEnum.RQB_02.getValue(), ReDJC.class, MapRelation.reDJC02);
		// 03热端实体封装
		JSONObject reDJC03 = mappingData(mes13Dto0047, time, EquipmentEnum.RQB_03.getValue(), ReDJC.class, MapRelation.reDJC03);
		// 04热端实体封装
		JSONObject reDJC04 = mappingData(mes13Dto0047, time, EquipmentEnum.RQB_04.getValue(), ReDJC.class, MapRelation.reDJC04);
		// 电表01实体封装
		JSONObject dianB01 = mappingData(mes13Dto0047, time, EquipmentEnum.DB_01.getValue(), DianB.class, MapRelation.dianB01);

		res.add(reDJC01);
		res.add(reDJC02);
		res.add(reDJC03);
		res.add(reDJC04);
		res.add(dianB01);
		return res;
	}

	/**
	 * 对象解析封装
	 * @param obj 元数据对象
	 * @param time 上报时间
	 * @param deviceName 设备名称
	 * @param tClass 目标对象class
	 * @param mapRelation 对象映射关系
	 * @param <T>
	 * @return
	 */
	public <T> JSONObject mappingData(Object obj,String time,String deviceName,Class<T> tClass,Map<String,String> mapRelation){
		// 获取目标对象的属性
		Field[] declaredFields = tClass.getDeclaredFields();
		T t = null;
		String value = "";
		try{
			// 获取目标对象的实例化对象
			t = tClass.newInstance();
			for (Field declaredField : declaredFields) {
				//设置属性可操作
				declaredField.setAccessible(true);
				//获取属性名称
				String name = declaredField.getName();
				//通过属性名称去hash映射中 获取对应的元数据key
				value = mapRelation.get(name);
				if (StringUtils.isBlank(value)) {
					continue;
				}
				// 通过属性名称 获取元数据的属性
				Field field = obj.getClass().getDeclaredField(value);
				// 获取元数据的实例化对象
				// 设置属性可操作
				field.setAccessible(true);
				// field.get(mes13Dto0001).toString() 获取元数据的属性值
				// 给目标对象属性赋值
				declaredField.set(t,field.get(obj).toString());
			}
		}catch (NoSuchFieldException e) {
			log.info("字段解析异常,对象不包含该字段,对象{} 字段{}",obj,value);
		} catch (InstantiationException e) {
			e.printStackTrace();
			log.info("目标对象实例化异常 {}",tClass);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			log.info("元数据属性获取异常, 元数据{}, 属性{}",obj,value);
		}
		// 封装推送数据
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("time",DateUtil.getLong(time,timeFormat));
		jsonObject.put("deviceName",deviceName);
		jsonObject.put("data",t);
		return jsonObject;
	}



}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值