JSON使用Newtonsoft将字符串值反序列化为List <t> - 构造函数arg在C#中为null

时间:2017-07-07 14:00:52

标签: c# json.net deserialization

我正在使用Newtonsoft库进行序列化和反序列化json对象。 参考代码如下:

 public abstract class BaseNode
{
    [JsonConstructor]
    protected BaseNode(string [] specifications)
    {
        if (specifications == null)
        {
            throw new ArgumentNullException();
        }
        if (specifications.Length == 0)
        {
            throw new ArgumentException();
        }

        Name = specifications[0];
        Identifier = specifications[1];
        //Owner = specifications[2];
    }

    public string Name{ get; protected set; }
    public string Identifier { get; protected set; }
    public string Owner { get; protected set; }
}


public class ComputerNode: BaseNode
{
    [JsonConstructor]
    public ComputerNode(string[] specifications):base(specifications)
    {
        Owner = specifications[2];
    }
}

序列化工作正常,我可以将json格式的数据保存在文件中。我正在将一个ComputerNode对象列表存储在一个文件中。 以下是文件读/写操作的代码:

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

        File.WriteAllText(path, ser);
    }

    public List<T> Read(string path)
    {
        var text = File.ReadAllText(path);

        var res =  JsonConvert.DeserializeObject<List<T>>(text);
        return res;
    }

}

预期文件读取结果应该是存储在文件中的ComputerNode对象列表。 但是,在反序列化时 - 创建ComputerNode的对象,会调用正确的构造函数,但参数(string [] specifications)为null。

有没有更好的方法来使用它。

请不要建议更改BaseNode.cs或ComputerNode.cs

感谢您的建议......

正确答案

用新的Json构造函数重写。在BaseNode.cs

    [JsonConstructor]
    public BaseNode(string Owner, string Name, string Identifier)
    {
        this.Name = Name;
        this.Identifier = Identifier;
    }

和 重写了Json构造函数 - ComputerNode.cs

    [JsonConstructor]
    public ComputerNode(string Owner, string Name, string Identifier):base(Owner, Name, Identifier)
    {
        this.Owner = Owner;
    }

2 个答案:

答案 0 :(得分:1)

https://stackoverflow.com/a/23017892/34092州:

  

构造函数参数名称与。匹配很重要   为此工作的JSON对象的相应属性名称   正确。

您的构造函数参数名为specifications。 JSON中没有名称为specifications的属性。这就是将值传递为null的原因。

另见http://www.newtonsoft.com/json/help/html/JsonConstructorAttribute.htm

答案 1 :(得分:0)

实际上如果你运行

var ser = JsonConvert.SerializeObject(nodes);
File.WriteAllText(path, ser);

其中节点是List&lt; T&gt;

然后

var text = File.ReadAllText(path);
var res =  JsonConvert.DeserializeObject<List<T>>(text);

其中res是List&lt; T&gt;

根据JsonConstructor文档:http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConstructorAttribute.htm

  

指示JsonSerializer在反序列化该对象时使用指定的构造函数。

否则会说有一个与要反序列化的字符串相关的构造函数参数。

实际上你指定的构造函数([JsonConstructor])尝试使用always null参数覆盖反序列化的结果

在你的情况下你应该

[JsonConstructor]
protected BaseNode()
{

}

避免构造函数与反序列化进行交互。

恕我直言,反序列化器永远不会(根据文档)给构造函数一个参数。