I am using Newtonsoft libraries for serialization and deserialization json object. The reference code is below:
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];
}
}
Serialization works fine and I can save the json formatted data in a file. I am storing a list of ComputerNode objects in a file. Following code for file read/write operation:
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;
}
}
The expected file Read result should be a list of ComputerNode objects stored in a file. However, while deserialization - creating an object of ComputerNode, correct constructor is called but the argument (string[] specifications) is null.
Is there any better way to work with it.
Please do not suggest to change BaseNode.cs or ComputerNode.cs
Thanks for suggestion...
Correct Answer
Overridden with new Json constructor. In BaseNode.cs
[JsonConstructor]
public BaseNode(string Owner, string Name, string Identifier)
{
this.Name = Name;
this.Identifier = Identifier;
}
and Overridden a Json constructor - ComputerNode.cs
[JsonConstructor]
public ComputerNode(string Owner, string Name, string Identifier):base(Owner, Name, Identifier)
{
this.Owner = Owner;
}
https://stackoverflow.com/a/23017892/34092 states:
It is important that the constructor parameter names match the corresponding property names of the JSON object for this to work correctly.
Your constructor parameter is called specifications
. There is no property in the JSON with the name of specifications
. This is why the value is passed as null.
See also http://www.newtonsoft.com/json/help/html/JsonConstructorAttribute.htm .
in practice if you run
var ser = JsonConvert.SerializeObject(nodes);
File.WriteAllText(path, ser);
where nodes is a List<T>
then
var text = File.ReadAllText(path);
var res = JsonConvert.DeserializeObject<List<T>>(text);
where res is a List<T>
According to the JsonConstructor
documentation: http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConstructorAttribute.htm
Instructs the JsonSerializer to use the specified constructor when deserializing that object.
No where it is said that there will be a constructor parameter related with the string to be deserialized.
in fact the constructor you designate ( [JsonConstructor]
) try to override the result of the deserialization with an always null parameter
In your case you should have
[JsonConstructor]
protected BaseNode()
{
}
to avoid the constructor over interacting with the deserialization.
IMHO, the deserializer will never (according to documentation) give a parameter to a constructor.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.