使用 System.Text.Json,我有一个包含一些属性的类,包括 System.Drawing.Font 属性。
序列化没有问题,但无法反序列化。 我收到错误“没有无参数构造函数的类型反序列化”
这是一个简化的示例:
当我单击button1时,我序列化了对象,但是当我单击button2进行反序列化时出现错误。
using System.Text.Json;
namespace WinFormsApp1;
public partial class Form1 : Form
{
private CasaSettings _casaSettings;
private string _stringJson;
public Form1()
{
InitializeComponent();
_casaSettings = new CasaSettings();
}
private void button1_Click(object sender, EventArgs e)
{
_casaSettings.DefaultFont = textBox1.Font;
_stringJson = JsonSerializer.Serialize(_casaSettings, _casaSettings.GetType());
}
private void button2_Click(object sender, EventArgs e)
{
CasaSettings convertedSetting = (CasaSettings)JsonSerializer.Deserialize(_stringJson, typeof(CasaSettings));
}
}
public class CasaSettings
{
public CasaSettings() { }
public int AlertIntervalRefresh { get; set; } = 60000;
public Font DefaultFont { get; set; } = new Font("Tahoma", (float)8.25, GraphicsUnit.Point);
}
我需要继续使用 System.Text.Json。 我想我需要使用转换器,但无法使其工作。
谢谢
Font
、Color
和 Icon
)具有内置的 类型转换器,由 Windows 窗体设计器使用,可将类型与字符串表示形式相互转换。 您可以在 a 中使用这些类型转换器将这些类型作为字符串序列化为某些 JsonConverter<T>
: 中的 JSON
public class TypeDescriptorJsonConverter<TValue> : JsonConverter<TValue>
{
static TypeConverter TypeConverter { get; } = TypeDescriptor.GetConverter(typeof(TValue));
static bool IsNonNullableValueType { get; } = typeof(TValue).IsValueType && Nullable.GetUnderlyingType(typeof(TValue)) == null;
public override TValue? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
reader.TokenType switch
{
JsonTokenType.Null when IsNonNullableValueType => throw new JsonException(),
JsonTokenType.Null => default,
JsonTokenType.String => (TValue?)TypeConverter.ConvertFromInvariantString(null, (string)reader.GetString()!),
_ => throw new JsonException()
};
public override void Write(Utf8JsonWriter writer, TValue? value, JsonSerializerOptions options)
{
if (value is null)
writer.WriteNullValue();
else
writer.WriteStringValue(TypeConverter.ConvertToInvariantString(null, value));
}
}
public static class JsonExtensions
{
public static JsonSerializerOptions AddWellKnownTypeDescriptorConverters(this JsonSerializerOptions options)
{
options.Converters.Add(new TypeDescriptorJsonConverter<System.Drawing.Color>());
options.Converters.Add(new TypeDescriptorJsonConverter<System.Drawing.Font>());
// Add any others as required e.g.
//options.Converters.Add(new TypeDescriptorJsonConverter<System.Drawing.Icon>());
return options;
}
}
然后为您的
JsonSerializerOptions
定义 Form1
,例如如下:
readonly JsonSerializerOptions _options = new JsonSerializerOptions()
{
// Add whatever other options you want here, e.g.:
WriteIndented = true,
}.AddWellKnownTypeDescriptorConverters();
并按如下方式使用它们:
_stringJson = JsonSerializer.Serialize(_casaSettings, _options);
CasaSettings convertedSetting = JsonSerializer.Deserialize<CasaSettings>(_stringJson, _options);
您的 JSON 将如下所示(添加了用于测试的
public Color Color { get; set; }
属性):
{
"AlertIntervalRefresh": 60000,
"DefaultFont": "Tahoma, 8.25pt",
"Color": "AliceBlue"
}
或者,您可以切换到 Json.NET,它支持自动使用应用的
TypeConverter
进行类型序列化。 Json.NET 是 .NET Framework 中首选的 JSON 序列化器,并且在 .NET Core 中也能正常工作。
首先通过nuget安装Newtonsoft.Json,然后修改代码如下:
using Newtonsoft.Json;
var _stringJson = JsonConvert.SerializeObject(_casaSettings, Formatting.Indented);
CasaSettings convertedSetting = JsonConvert.DeserializeObject<CasaSettings>(_stringJson);
您的
CasaSettings
将往返于 JSON,无需创建任何自定义转换器。 JSON 格式将与上面显示的 System.Text.Json 格式相同。