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

时间:2014-06-16 12:27:56

标签: c# json serialization json.net

我需要将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类的对象,因为我的默认构造函数是私有的,我得到的对象属性为NULL

我正在使用Newtonsoft Json解析器。

5 个答案:

答案 0 :(得分:32)

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

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

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

修改

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

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

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

答案 1 :(得分:2)

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

使用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;
    }
}

答案 2 :(得分:1)

无需创建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;
    }

}

一切顺利!

答案 3 :(得分:0)

不幸的是,根据thisthis,这不是新的System.Text.Json.JsonSerializer(Newtonsoft.Json的核心版本)的选项。

System.Text.Json仅支持无参数构造函数

答案 4 :(得分:0)

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

public class Test
{
    public string Property { get; }

    public Test(string property)
    {
        Property = property;
    }
}

Console.WriteLine(
  JsonConvert.DeserializeObject(new Test("Instance")));

Newtonsoft.Json 支持使用开箱即用的构造函数参数初始化属性,无需设置任何其他属性或更改任何设置。唯一的限制是参数名称必须与属性名称不区分大小写。