c# - 如何更改数字反序列化的默认类型?

标签 c# json.net

我正在将一些属性反序列化为 Dictionary<string, object> .

当我反序列化一些 json 时,它会填充 DictionaryInt64对象而不是 Int32 .我希望它选择 Int32作为默认值,我知道我可以使用会在转换时溢出的 javascript Numerics。在这种情况下抛出异常是完全可以接受的。

有什么办法可以实现吗?我希望有一些不错的属性或方便的接口(interface)可以实现并添加到 JsonSerializer .而且我担心我必须深入到 Json.NET 的深处。

基本上我想有一些方法来控制对象的已知类型,这样我就可以得到 Int32的而不是 Int64DateTimes而不是 Strings .

最佳答案

据我所知,没有内置的方法可以做到这一点。

有一个 issue关于这个主题,但它已被关闭。 作者对该问题的一些评论:

Json.NET by default reads integer values as Int64 because there is no way to know whether the value should be Int32 or Int64, and Int64 is less likely to overflow. For a typed property the deserializer knows to convert the Int64 to a Int32 but because your property is untyped you are getting an Int64. [...] It is just the way Json.NET has to work.

最简单的解决方案当然是将类型更改为 Dictionary<string, int> , 但我想你不仅在阅读数字,而且还被 object 困住了。 .

另一种选择是使用 Serialization Callbacks并手动转换那些 Int64 s 至 Int32或创建您自己的 Contract Resolver JsonConverter并直接控制(反)序列化。


编辑:我创建了一个更具体的小示例。

这是一个非常基本的转换器,只适用于您的特定词典:

public class Int32Converter : JsonConverter {
    public override bool CanConvert(Type objectType) {
        // may want to be less concrete here
        return objectType == typeof(Dictionary<string, object>);
    }

    public override bool CanWrite {
        // we only want to read (de-serialize)
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        // again, very concrete
        Dictionary<string, object> result = new Dictionary<string, object>();
        reader.Read();

        while (reader.TokenType == JsonToken.PropertyName) {
            string propertyName = reader.Value as string;
            reader.Read();

            object value;
            if (reader.TokenType == JsonToken.Integer)
                value = Convert.ToInt32(reader.Value);      // convert to Int32 instead of Int64
            else
                value = serializer.Deserialize(reader);     // let the serializer handle all other cases
            result.Add(propertyName, value);
            reader.Read();
        }

        return result;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        // since CanWrite returns false, we don't need to implement this
        throw new NotImplementedException();
    }
}

您可以使用属性来装饰您的转换器成员或 pass it as parameter到(反)序列化方法。这是我使用属性的示例:

    [JsonObject]
public class MyObject {
    [JsonConverter(typeof(Int32Converter))]
    public Dictionary<string, object> Properties { get; set; }
}

下面是我用来测试实现的代码:

class Program {
    static void Main(string[] args) {
        MyObject test = new MyObject();
        test.Properties = new Dictionary<string, object>() { { "int", 15 }, { "string", "hi" }, { "number", 7 } };
        Print("Original:", test);

        string json = JsonConvert.SerializeObject(test);
        Console.WriteLine("JSON:\n{0}\n", json);

        MyObject parsed = JsonConvert.DeserializeObject<MyObject>(json);
        Print("Deserialized:", parsed);
    }

    private static void Print(string heading, MyObject obj) {
        Console.WriteLine(heading);
        foreach (var kvp in obj.Properties)
            Console.WriteLine("{0} = {1} of {2}", kvp.Key, kvp.Value, kvp.Value.GetType().Name);
        Console.WriteLine();
    }
}

如果没有转换器,结果将是:

Deserialized:
int = 15 of Int64
string = hi of String
number = 7 of Int64

与转换器一起它是:

Deserialized:
int = 15 of Int32
string = hi of String
number = 7 of Int32

关于c# - 如何更改数字反序列化的默认类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8297541/

相关文章:

c# for 循环错误的迭代次数

C# 使用 HttpWebResponse 获取 JSON 编码的字典以及错误的状态代码

c# - 在 C# 中使用 Newtonsoft.JSON 努力反序列化 JSON 字符串

json - 如何在文本框中显示 JSON 结果而不是写入控制台?

c# - Microsoft.Extensions.DependencyInjection : DI'd code runs fine on dotnet CLI/Rider default . NET 配置文件,但导致 VS2022 崩溃

c# - Linq Where Clauses - 更好地堆叠或组合?

json.net - 将 Newtonsoft.Json.JsonConvert 的比较器设置为用于 HashSet/Dictionary

json.net - StringEnumConverter 用作属性但不是全局的

c# - MaskedEditValidator 在使用 "en-GB"文化时导致 Page.IsValid 为假

c# - 从 .doc MS Word 文件存储数学方程式并恢复它们