c# - JSON.net:如何在不使用默认构造函数的情况下反序列化?

我有一个类,它有一个默认构造函数,还有一个接受一组参数的重载构造函数。这些参数与对象上的字段匹配,并在构造时分配。在这一点上,我需要默认构造函数用于其他目的,所以如果可以的话,我想保留它。

我的问题:如果我删除默认构造函数并传入 JSON 字符串,对象会正确反序列化并传入构造函数参数而不会出现任何问题。我最终以我期望的方式取回了填充的对象。但是,一旦我将默认构造函数添加到对象中,当我调用 JsonConvert.DeserializeObject<Result>(jsontext)不再填充属性。

此时我已尝试添加 new JsonSerializerSettings(){CheckAdditionalContent = true}到反序列化调用。那没有任何作用。

另一个注意事项:构造函数参数确实与字段名称完全匹配,只是参数以小写字母开头。我不认为这很重要,因为就像我提到的那样,反序列化可以在没有默认构造函数的情况下正常工作。

这是我的构造函数示例:

public Result() { }

public Result(int? code, string format, Dictionary<string, string> details = null)
{
    Code = code ?? ERROR_CODE;
    Format = format;

    if (details == null)
        Details = new Dictionary<string, string>();
    else
        Details = details;
}

最佳答案

Json.Net 更喜欢在对象上使用默认(无参数)构造函数(如果有的话)。如果有多个构造函数并且您希望 Json.Net 使用非默认构造函数,则可以将 [JsonConstructor] 属性添加到您希望 Json.Net 调用的构造函数。

[JsonConstructor]
public Result(int? code, string format, Dictionary<string, string> details = null)
{
    ...
}

构造函数参数名称必须与 JSON 对象的相应属性名称匹配(忽略大小写)才能正常工作。但是,您不必为对象的每个属性都有一个构造函数参数。对于那些没有被构造函数参数覆盖的 JSON 对象属性,Json.Net 将在构造对象后尝试使用公共(public)属性访问器(或标记为 [JsonProperty] 的属性/字段)来填充对象.

如果您不想为您的类添加属性或不想控制您尝试反序列化的类的源代码,那么另一种选择是创建自定义 JsonConverter实例化和填充您的对象。例如:

class ResultConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Result));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Load the JSON for the Result into a JObject
        JObject jo = JObject.Load(reader);

        // Read the properties which will be used as constructor parameters
        int? code = (int?)jo["Code"];
        string format = (string)jo["Format"];

        // Construct the Result object using the non-default constructor
        Result result = new Result(code, format);

        // (If anything else needs to be populated on the result object, do that here)

        // Return the result
        return result;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后,将转换器添加到您的序列化器设置中,并在反序列化时使用这些设置:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new ResultConverter());
Result result = JsonConvert.DeserializeObject<Result>(jsontext, settings);

https://stackoverflow.com/questions/23017716/

相关文章:

android - 如何在 Android 中解析 JSON?

c# - 在 JSON.NET 中反序列化的转换接口(interface)

json - 如何在结构中定义多个名称标签

javascript - 如何动态创建 JavaScript 数组(JSON 格式)?

android - 如何在 Android 中使用 HTTPClient 以 JSON 格式发送 P

javascript - 通过 JavaScript 动态创建 JSON 对象(没有连接字符串)

mysql - 在 MySQL 中以 JSON 格式存储数据

python - json.load() 和 json.loads() 函数有什么区别

json - 如何在 ECMAScript 6 中导入 JSON 文件?

javascript - 从AngularJS中的对象数组中通过id获取特定对象