public class Entity { private Dictionary<string, object> component = new Dictionary<string, object>(); public void Set(string key, object value) { this.component[key] = value; } public T Get<T>(string key) where T : class { if (!this.component.ContainsKey(key)) { return null; } return (T)this.component[key]; } public int? Get(string key) { if (!this.component.ContainsKey(key)) { return null; } return (int)this.component[key]; } }
public static class JsonHelper { public static string ToString(object obj) { return JsonConvert.SerializeObject(obj); } public static T FromString<T>(string str) { return JsonConvert.DeserializeObject<T>(str); } }
var entity = new Entity(); entity.Set("health", 10); string entityString = JsonHelper.ToString(entity); var entity2 = new Entity(); JsonHelper.FromString<Entity>(entityString); Assert.AreEqual(10, entity2.Get("health"));
居然反序列化后,对象无法还原
你的Entity类,都没属性,你让它怎么还原?
可以尝试修改为内部类,别用Dictionary~
[JsonObject] public class Entity { public Entity() { this.Component = new Dictionary<string, object>(); } [JsonProperty] public Dictionary<string, object> Component { get; private set; } public void Set(string key, object value) { this.Component[key] = value; } public T Get<T>(string key) where T : class { if (!this.Component.ContainsKey(key)) { return null; } return (T)this.Component[key]; } public int? Get(string key) { if (!this.Component.ContainsKey(key)) { return null; } return (int)this.Component[key]; } }
改成这样了,还是不行……
好吧,犯了个sb错误
var entity2 = JsonHelper.FromString<Entity>(entityString);
@唐诗: 这,能行吗?行的话你就赢了~
试了一下,你的第二个例子是能正确的序列化和反序列化的。序列化的时候将其序列化了为{"component":{"health":10}}这样的字符串,但反序列化的时候对于10这个数字,是将其转换了为int64的这种类型的,然后在Get函数中将int64类型强制转换为int类型抛异常。
下列简化后的代码就能简单的复现这个异常:
int k = 10; var jsonString = JsonHelper.ToString(k); Console.WriteLine(jsonString); object obj = JsonHelper.FromString<object>(jsonString); Console.WriteLine(obj.GetType()); Console.WriteLine((int)obj);
你的这个例子用xml序列化或二进制序列化都不会有问题,究其原因,并不是json.net的bug,而是json字符串本身携带的信息较少,它并不携带严格的类型信息(你比较一下json序列化的后的字符串和xml序列化后的字符串就清楚了),因此无法保证object类型能够正确反序列化。
对于你这个问题,非要用json来序列化的话,要么把Component 定义为Dictionary<string, int>这样的强类型,要么把Get的返回值改成int64?。