gpt4 book ai didi

c# - 创建自定义 JsonConverter 来处理 System.Text.Encoding 对象

转载 作者:行者123 更新时间:2023-11-30 18:24:09 25 4
gpt4 key购买 nike

我写了一个自定义的 JsonConverter,我希望它能让我序列化和反序列化 Encoding我的类中的对象:

public class EncodingConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsSubclassOf(typeof(Encoding));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((Encoding)value).EncodingName);
}

public override bool CanRead { get { return true; } }

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var name = reader.ReadAsString();
return Encoding.GetEncoding(name);
}
}

但是,当我运行以下测试代码时,在调用 DeserializeObject 时出现异常,而且 ReadJson 方法永远不会被调用。

class Program
{
private static void Main(string[] args)
{
var test = new TestClass();

var jsonSettings = new JsonSerializerSettings
{
Converters = new[] { new EncodingConverter(), }
};

var json = JsonConvert.SerializeObject(test, jsonSettings);

var test2 = JsonConvert.DeserializeObject<TestClass>(json, jsonSettings);
}
}

class TestClass
{
public string Property1;
public Encoding Encoding = Encoding.UTF8;
}

异常信息是:

Target type System.Text.Encoding is not a value type or a non-abstract class.

我错过了什么吗?

最佳答案

我发现您的转换器存在三个问题。

  1. 您在 CanConvert() 中使用了错误的检查。
  2. 您在序列化时使用了错误的 Encoding 名称。
  3. 反序列化时,您使用了错误的方法从读取器获取值。

让我们一次拿这些。

首先,在您的 CanConvert 方法中,您使用 objectType.IsSubclassOf(typeof(Encoding)) 来确定转换器是否应该处理 Encoding。这在序列化上工作得很好,因为你有一个编码的具体实例(例如 UTF8Encoding),它确实是 Encoding 的子类。然而,在反序列化时,反序列化器并不知道你要进行什么具体的编码类型,所以传递给转换器的类型只是Encoding。由于 Encoding 不是其自身的子类,因此 CanConvert 返回 false,并且您的 ReadJson 方法永远不会被调用。这让 Json.Net 尝试实例化 Encoding 本身,这是它做不到的(因为 Encoding 是抽象的),所以它会抛出你在问题中提到的错误.您应该在 CanConvert 方法中使用 typeof(Encoding).IsAssignableFrom(objectType)

其次,在 WriteJson 中序列化 Encoding 时,您正在输出 EncodingName 属性,这是人类可读的显示名称编码,而不是代码页名称。如果您查看 Encoding.GetEncoding(string) 的文档方法,它说:

Parameters

name

Type: System.String

The code page name of the preferred encoding. Any value returned by the WebName property is valid. Possible values are listed in the Name column of the table that appears in the Encoding class topic.

因此,如果您希望能够使用此值稍后重建 ,则应该在 WriteJson 方法中输出 WebName 属性的值在 ReadJson 中编码

第三,在您的 ReadJson 方法中,您使用 reader.ReadAsString() 尝试从 JSON 中获取编码名称。这不会像您预期的那样工作。当ReadJson被Json.Net调用时,reader已经定位到当前值。当您调用 ReadAsString() 时,阅读器会前进到下一个 标记,然后尝试将该标记解释为字符串。您真正想要做的只是获取当前标记的值,您可以使用 Value 属性来实现。因为 Valueobject 类型,您需要将其转换为字符串。

这是转换器的更正代码:

public class EncodingConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Encoding).IsAssignableFrom(objectType);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((Encoding)value).WebName);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return Encoding.GetEncoding((string)reader.Value);
}
}

fiddle :https://dotnetfiddle.net/UmLynX

关于c# - 创建自定义 JsonConverter 来处理 System.Text.Encoding 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31623450/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com