前段时间做了一个即时通讯项目,用的是腾讯云的IM服务,客户端内嵌腾讯云IM sdk,发消息的时候消息先发送到腾讯云服务器,腾讯云服务器再回调我们的接口,完成消息入库。问题来了,腾讯云的消息体内格式不是固定的,我们如何将数据封装到Java类里面去呢? 答案就是用jackson
腾讯云消息格式参见消息格式
代码中的@Getter等注解都是lombok注解。
腾讯云消息格式大致如下:
{
//为了方便起见,json中只保留MsgBody,实际数据中还有很多与MsgBody平级的字段
"MsgBody": [
{
"MsgType": "TIMTextElem",
"MsgContent": {
"Text": "hello"
}
},
{
"MsgType": "TIMFaceElem",
"MsgContent": {
"Index": 1,
"Data": "content"
}
},
{
"MsgType": "TIMTextElem",
"MsgContent": {
"Text": "world"
}
}
]
}
MsgBody是消息数据体,当里面只有一个对象的时候是单条消息,如果有多个对象的时候是组合消息。比如上面的json格式就是一个文本+表情+文本的组合消息。为方便说明,本文都以文本消息和表情消息为例说明
针对腾讯云的每一种消息,我们都定义了一个消息格式类。
我们将MsgBody里面每一个对象抽象成一个类,对应的类定义如下:
@ToString
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class TimMsgElement implements BaseVO {
@JsonProperty("MsgContent")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "MsgType", visible = true)
private TimMsgElementContent msgContent;
@JsonProperty("MsgType")
private String msgType;
}
下面我们为每一种MsgContent定义一个类
MsgType为TIMTextElem的MsgContent类如下:
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString
public class TimTextMsgElementContent extends TimMsgElementContent {
@JsonProperty("Text")
private String text;
}
MsgType为TIMFaceElem的MsgContent类如下:
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString
public class TimFaceMsgElementContent extends TimMsgElementContent {
/**
* 表情索引,用户自定义。
*/
@JsonProperty(value = "Index")
private Integer index;
/**
* 额外数据
*/
@JsonProperty(value = "Data")
private String data;
}
父类TimMsgElementContent的定义如下:
@Data
@JsonSubTypes({
@JsonSubTypes.Type(name = "TIMTextElem", value = TimTextMsgElementContent.class),
@JsonSubTypes.Type(name = "TIMFaceElem", value = TimFaceMsgElementContent.class),
})
public class TimMsgElementContent implements Serializable {
}
@JsonTypeInfo注解用于定义根据哪个字段将数据封装到哪个类中。这里用MsgType字段
@JsonSubTypes注解用于定义MsgType与MsgContent的关系。如此jackson便知道当MsgType=TIMTextElem的时候应该用TimTextMsgElementContent去封装MsgContent数据,当MsgType=TIMFaceElem的时候应该用TimFaceMsgElementContent去封装MsgContent数据。