【发布时间】:2021-10-01 12:09:16
【问题描述】:
我想反序列化具有字典
目前我正在尝试实现自定义 JsonConverter。问题是我的代码在 CustomJsonConverter.WriteJson() 函数中失败。 JObject.FromObject() 引发空异常。 我做错了什么?
一个完整的控制台项目:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Linq;
namespace HowToSerializeJson
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var map = new Map();
var modules = new Dictionary<string, Module>
{
{"test1", new Module1("id1")},
{"test2", new Module2("id2")},
};
map.Modules = modules;
map.SaveJson();
map.LoadJson();
}
}
class Map
{
public Dictionary<string,Module> Modules { get; set; }
public bool LoadJson()
{
try
{
if (File.Exists("mapping.json"))
{
using (StreamReader file = File.OpenText("$mapping.json"))
{
var text = file.ReadToEnd();
var json = JsonConvert.DeserializeObject(text, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
var map = json as Map;
Modules = map.Modules;
}
return true;
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return false;
}
public bool SaveJson()
{
using (StreamWriter file = File.CreateText("mapping.json"))
{
var json = JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
file.Write(json);
}
return false;
}
}
[JsonConverter(typeof(CustomJsonConverter))]
class Module
{
public string Id { get; set; }
public Module(string id)
{
Id = id;
}
}
[JsonConverter(typeof(CustomJsonConverter))]
class Module1 : Module
{
public string Prop1 { get; set; } = "1";
public Module1(string id) : base(id)
{
}
}
[JsonConverter(typeof(CustomJsonConverter))]
class Module2 : Module
{
public string Prop1 { get; set; } = "2";
public Module2(string id) : base(id)
{
}
}
public class CustomJsonConverter : JsonConverter
{
public List<Type> Types { get; set; } = Assembly.GetAssembly(typeof(CustomJsonConverter)).GetTypes().ToList();
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
try
{
var jObj = JObject.FromObject(value, serializer);
jObj.AddFirst(new JProperty("type", value.GetType().Name));
jObj.WriteTo(writer);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var obj = JObject.Load(reader);
var typeKey = obj["$type"];
if (typeKey == null)
{
throw new InvalidOperationException("Cannot deserialize object w/o 'type' property.");
}
obj.Remove("type");
var type = Types.First(x => x.Name == typeKey.Value<string>());
var contract = serializer.ContractResolver.ResolveContract(type);
var value = contract.DefaultCreator();
if (value == null)
{
throw new JsonSerializationException("No object created.");
}
using (var subReader = obj.CreateReader())
{
serializer.Populate(subReader, value);
}
return value;
}
public override bool CanConvert(Type objectType)
{
return Types.Contains(objectType);
}
}
}
如果 ReadJson()(或整个方法)有问题,我会为每一个输入感到高兴。
【问题讨论】: