繁体   English   中英

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

[英]Deserialize json into C# object for class which has default private constructor

我需要为以下课程反序列化 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" }"

我应该如何创建 Test 类的对象,因为我的默认构造函数是私有的,并且我正在获取Property 为 NULL 的对象

我正在使用 Newtonsoft Json 解析器。

您可以通过使用[JsonConstructor]属性标记来让 Json.Net 调用私有构造函数:

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

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


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

JsonSerializerSettings settings = new JsonSerializerSettings
{
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};

Test t = JsonConvert.DeserializeObject<Test>(json, settings);

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

使用 Json.NET v6.0.8,以下 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;
    }
}

无需在此处创建 Serializer 设置并分配 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 调用正确的(未参数化的)构造函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM