尝试使用 Font 反序列化类并获取:没有无参数构造函数的类型反序列化

问题描述 投票:0回答:1

使用 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。 我想我需要使用转换器,但无法使其工作。

谢谢

c# winforms serialization fonts system.text.json
1个回答
0
投票

许多 WinForms 原语(例如

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 格式相同。

© www.soinside.com 2019 - 2024. All rights reserved.