下方含git地址
代码中含有单元测试用例,作使用参考
适用场景
最近接收了一个 消息中心 模块的需求,此模块为消息起到消息中转、筛选,以及对消息按照一定规则进行重新组织(删减订阅方不需要的信息,以减小消息体大小,筛选需要的消息进行转发,迎合订阅方需求重新组织数据的需求)。
综上,根本问题在于解析消息内容,且不依赖具体的数据结构。
思路
方案1
- 需要一种树形、有层次结构的数据结构,该结构可以按照路径返回其某一节点的值;
- 该结构可以根据消息体动态自我扩充,也可以将扩充和解析分开,根据消息体的模板扩充,完整的结构可以解析消息体;
方案2
- 利用Jobject 直接解析,相比方案1性能上可能略差(内部有拆装箱操作),但几乎不用关心格式异常问题,以及各种不常用的json标准格式(比如单引号标识key是合法的,但编码时可能考虑不到),老实说再写一遍也难比这个性能高很多;
- 需要设计映射的数据结构;
实现
方案1 仍在实现当中,确定了分为节点,叶子节点,数组节点 三种结构,根据消息动态扩充内容,当前节点根据终结符类型,判定在节点后添加兄弟节点或者子节点,因为没有实现完整,这里仅提出构想,不分享这部分代码了
方案2 因为不用关心json的解析问题,实现起来较为简单
一般的时候我们只需要这个作为映射的数据结构,路径用特定的符号分隔层级,一层层去找
[Serializable]
public class JsonMappingTerm
{
public string Source {
get; set; }
public string Target {
get; set; }
}
可是会有这种情况
{
"ID": "001",
"Name": "test",
"Mark": "Hello Word",
"test": "{\"ID\":\"001\",\"Name\":\"test\",\"Mark\":\"Hello Word\"}"
}
当然这并不妨碍我们一级一级的向下找,但是在重复读取test内部的数据时会进行反复的序列化、反序列化,或者将反序列化后的内容缓存是一种解决方案,但这似乎并不合理
于是引入了上下文概念,MappingTerms 仅充当字段映射,不含分隔符
/// <summary>
/// 映射上下文
/// </summary>
/// <remarks>
/// 为解决json中存在的序列化为string的对象的反序列化问题,以及数组的操作差异问题
/// 引入上下文概念
/// </remarks>
[Serializable]
public class MappingContext
{
/// <summary>
/// source路径
/// .为分隔符
/// 后缀为Mappingsymbol,以便实现特定操作
/// </summary>
public string SLocation {