仓库
思路
在LitJson进行Object反序列化的时候检查是否有__type字段,如果有,按照__type字段的string类型实例化。
使用示例
using System.Diagnostics;
using LitJson;
public class Program
{
public static void Main(string[] args)
{
var snake = new Snake() { Length = 1f };
var bird = new Bird() { FootCount = 1};
var lion = new Lion() { Food = bird };
List<Animal> animals = new List<Animal>() { snake, bird, lion };
var jsonStr = JsonMapper.ToJson(animals);
var outputAnimals = JsonMapper.ToObject<List<Animal>>(jsonStr);
Debug.Assert(((Bird)outputAnimals[1]).FootCount == 1);
}
public class Animal
{
public string __type;
public bool Alive { get; set; }
public Animal()
{
__type = GetType().AssemblyQualifiedName;
}
}
public class Pet: Animal
{
public string MasterName { get; set; }
}
public class Snake: Pet
{
public float Length { get; set; }
}
public class Bird: Pet
{
public int FootCount { get; set; }
}
public class Lion: Animal
{
public Animal Food { get; set; }
}
}
核心代码
if (t_data.Properties.TryGetValue("__type", out var typeMeta) && check__type)
{
if (typeMeta.Type == typeof(string))
{
int count = 1;
StringBuilder sb = new StringBuilder();
sb.Append("{\"");
while (count > 0)
{
var c = reader.ReadChar();
if (c == -1)
{
throw new JsonException("Cannot Find } For {");
}
if (c == '{')
{
count++;
}
if (c == '}')
{
count--;
}
sb.Append((char)c);
}
// 词法分析器目前期望string输入 跳过后重置为初始状态
reader.SetLexerState(1);
// 移除ObjectPrime 期望下一个读入}
reader.PopAutoMatonStack();
reader.PushAutoMatonStack('}');
// 原本是" 表示开始读属性 强制伪装成结束 故而会直接返回ObjectEnd
reader.SetCurrentInput('}');
// 对应于ReadValue函数的最后return instace 也即返回{} null 需要在List中移除多余的null
var objStr = sb.ToString();
var data = JsonMapper.ToObject(objStr);
Type type = Type.GetType(data["__type"].ToString());
if (type == null)
{
throw new JsonException("__type Field Is Not A Type Name");
}
else
{
return ReadValue(type, new JsonReader(objStr), false);
}
}
}