使用TypeNameHandling.All时替换$type的Json序列化/反序列化方案
解决Json.NET序列化$type键适配Firebase的问题
问题场景
现有Car类定义:
public class Car { public int Speed = 0; }
用Json.NET开启TypeNameHandling.All序列化时:
var str = JsonConvert.SerializeObject(new Car(), new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
会生成带$type键的JSON:
{ "$type":"Car", "Speed": 0 }
但Firebase实时数据库不允许键包含$,得把$type换成自定义键(比如typeKey),同时保证反序列化时能正常识别类型信息。
最优实现方案:自定义JsonConverter
写一个自定义转换器,双向处理类型键的替换,不破坏原有序列化逻辑:
public class FirebaseTypeConverter : JsonConverter { private const string CustomTypeKey = "typeKey"; private const string OriginalTypeKey = "$type"; public override bool CanConvert(Type objectType) { // 适配所有需要类型标识的对象 return true; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 先把对象序列化到JObject var jObject = JObject.FromObject(value, serializer); // 替换$type为自定义键 if (jObject.ContainsKey(OriginalTypeKey)) { var typeValue = jObject[OriginalTypeKey]; jObject.Remove(OriginalTypeKey); jObject.Add(CustomTypeKey, typeValue); } // 输出处理后的JSON jObject.WriteTo(writer); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 读取JSON到JObject var jObject = JObject.Load(reader); // 把自定义键换回$type,让Json.NET能识别类型 if (jObject.ContainsKey(CustomTypeKey)) { var typeValue = jObject[CustomTypeKey]; jObject.Remove(CustomTypeKey); jObject.Add(OriginalTypeKey, typeValue); } // 按正常逻辑反序列化 return jObject.ToObject(objectType, serializer); } }
使用方式
序列化
把自定义转换器加入序列化配置:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, Converters = new List<JsonConverter> { new FirebaseTypeConverter() } }; var str = JsonConvert.SerializeObject(new Car(), settings);
生成的JSON就会变成符合Firebase要求的格式:
{ "typeKey":"Car", "Speed": 0 }
反序列化
同样用带转换器的配置反序列化即可:
var car = JsonConvert.DeserializeObject<Car>(str, settings);
补充说明
- 转换器会自动处理类型键的双向替换,不影响其他属性的序列化/反序列化
- 即使是多态场景(比如父类子类的序列化)也能正常工作,因为只是替换键名,类型信息内容保持不变
- 可以直接修改
CustomTypeKey的值,换成任何符合Firebase规则的键名
内容的提问来源于stack exchange,提问作者Whyser
相关产品推荐
相关产品推荐

