且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-01-17 12:48:49

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

Json.Net prefers to use the default (parameterless) constructor on an object if there is one. If there are multiple constructors and you want Json.Net to use a non-default one, then you can add the [JsonConstructor] attribute to the constructor that you want Json.Net to call.

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

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

It is important that the constructor parameter names match the corresponding property names of the JSON object (ignoring case) for this to work correctly. You do not necessarily have to have a constructor parameter for every property of the object, however. For those JSON object properties that are not covered by the constructor parameters, Json.Net will try to use the public property accessors (or properties/fields marked with [JsonProperty]) to populate the object after constructing it.

如果您不想向类添加属性,或者不想以其他方式控制要反序列化的类的源代码,则另一种选择是创建自定义 JsonConverter 来实例化和填充您的对象.例如:

If you do not want to add attributes to your class or don't otherwise control the source code for the class you are trying to deserialize, then another alternative is to create a custom JsonConverter to instantiate and populate your object. For example:

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();
    }
}

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

Then, add the converter to your serializer settings, and use the settings when you deserialize:

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