将json反序列化为具有默认私有构造函数的类的c#对象

本文关键字:构造函数 对象 默认 json 反序列化 | 更新日期: 2023-09-27 18:08:44

我需要为下面的类反序列化json。

public class Test
{
    public string Property { get; set; }
    private Test()
    {
        //NOTHING TO INITIALIZE
    }
    public Test(string prop)
    {
        Property = prop;
    }
}
我可以创建一个Test的实例,比如
var instance = new Test("Instance");

考虑到我的json类似于

"{  "Property":"Instance" }"

我如何创建一个测试类的对象作为我的默认构造函数是私有的,我正在获得对象,其中属性是NULL

我使用Newtonsoft Json解析器

将json反序列化为具有默认私有构造函数的类的c#对象

你可以制作Json。Net调用私有构造函数,用[JsonConstructor]属性标记它:

[JsonConstructor]
private Test()
{
    //NOTHING TO INITIALIZE
}

请注意,在调用构造函数后,序列化器仍将使用公共setter来填充对象。


另一个可能的选择是使用ConstructorHandling设置:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
Test t = JsonConvert.DeserializeObject<Test>(json, settings);

你似乎不需要采取任何额外的步骤。

使用Json。下面的c#程序可以在LINQPad中工作:

void Main()
{   
    var o = JsonConvert.DeserializeObject<Test>("{'"Property'":'"Instance'"}");
    Debug.Assert(o.Property == "Instance",
        "Property value not set when deserializing.");
}
public class Test
{
    public string Property { get; set; }
    private Test()
    {
    }
    public Test(string propertyValue)
    {
        Property = propertyValue;
    }
}

不需要在这里创建序列化器设置并指定ConstructorHandling。请记住在私有构造函数中定义[JsonConstructor]属性。我对抽象的BaseNode.cs及其具体的ComputerNode.cs实现也有类似的情况。您可以创建类,复制/粘贴下面的代码并做一些实验。

    public abstract class BaseNode
{
    [JsonConstructor] // ctor used when Json Deserializing
    protected BaseNode(string Owner, string Name, string Identifier)
    {
        this.Name = Name;
        this.Identifier = Identifier;
    }
    // ctor called by concrete class.
    protected BaseNode(string [] specifications)
    {
        if (specifications == null)
        {
            throw new ArgumentNullException();
        }
        if (specifications.Length == 0)
        {
            throw new ArgumentException();
        }
        Name = specifications[0];
        Identifier = specifications[1];
    }
    public string Name{ get; protected set; }
    public string Identifier { get; protected set; }
}

public class ComputerNode: BaseNode
{
    public string Owner { get; private set; }
    [JsonConstructor] // not visible while creating object from outside and only used during Json Deserialization.
    private ComputerNode(string Owner, string Name, string Identifier):base(Owner, Name, Identifier)
    {
        this.Owner = Owner;
    }
    public ComputerNode(string[] specifications):base(specifications)
    {
        Owner = specifications[2];
    }
}

对于JSon读取和写入以下代码有帮助-

    public class Operation<T>
{
    public string path;
    public Operation()
    {
        var path = Path.Combine(Directory.GetCurrentDirectory(), "nodes.txt");
        if (File.Exists(path) == false)
        {
            using (File.Create(path))
            {
            }
        }
        this.path = path;
    }
    public void Write(string path, List<T> nodes)
    {
        var ser = JsonConvert.SerializeObject(nodes, Formatting.Indented);
        File.WriteAllText(path, ser);
    }
    public List<T> Read(string path)
    {
        var text = File.ReadAllText(path);
        var res =  JsonConvert.DeserializeObject<List<T>>(text);
        return res;
    }
}

一切顺利!

今天的简短答案是:将构造函数参数prop重命名为property,您的代码将正常工作。

public class Test
{
    public string Property { get; }
    public Test(string property)
    {
        Property = property;
    }
}
Console.WriteLine(
  JsonConvert.DeserializeObject(new Test("Instance")));

Newtonsoft。Json支持使用开箱即用的构造函数参数初始化属性,而不需要设置任何附加属性或更改任何设置。唯一的约束是参数名需要是与属性名不区分大小写的匹配。

我今天发现有一个公共构造函数接受参数而没有声明的非参数化构造函数会导致NewtonSoft尝试调用它唯一能找到的公共构造函数,因为没有显式的默认构造函数,而且它显然不能找到并调用框架提供的默认构造函数,除非是唯一的构造函数

显式声明默认构造函数导致NewtonSoft调用正确的(未参数化的)构造函数。