我有以下C#对象:
public abstract partial class ClientTreeNode {
public int ID { get; internal set; }
public string Question { get; internal set; }
public List<ClientTreeNode> Children { get; internal set; }
public QuestionCategories Category { get; internal set; }
public Dictionary<object, List<int>> AnswerNodes { get; internal set; }
public string Type => GetType().Name.Replace("TreeNode", "").FirstCharacterToLower();
public string CategoryText {
get {
switch (Category) {
case QuestionCategories.VisualInspection:
return "Sichtprüfung";
case QuestionCategories.MechanicalInspection:
return "Mechanische Prüfung";
case QuestionCategories.ElectricalInspection:
return "Elektrische Prüfung";
default:
return "Fehler";
}
}
}
public abstract AnswerResult Answer(JObject data);
internal static ClientTreeNode FromDatabase(int ID, out int TotalChildNodes) {
// ....
}
internal static int SumUpChildNodes(List<int> nodeIDs) {
using (var db = new DatabaseEntities()) {
return db.TreeNodes
.Where(tn => nodeIDs.Contains(tn.ID))
.Sum(tn => tn.TotalChildNodes);
}
}
[JsonConverter(typeof(StringEnumConverter), true)]
public enum QuestionCategories {
VisualInspection,
MechanicalInspection,
ElectricalInspection
}
}
public class YesNoTreeNode : ClientTreeNode {
public bool Result { get; internal set; }
public override AnswerResult Answer(JObject data) {
if (data["result"].Type != JTokenType.Boolean)
throw new ArgumentException("The provided answer was invalid.");
Result = data["result"].Value<bool>();
Children = new List<ClientTreeNode>();
foreach (var childNodeID in AnswerNodes[Result])
Children.Add(FromDatabase(childNodeID, out _));
return new AnswerResult(SumUpChildNodes(AnswerNodes[!Result]), Children);
}
}
JSON文件如下所示:
{"AnswerNodes":{"True":[4],"False":[5]}}
有时候,它可能会更高级。但这并非在所有情况下都是强制性的:
{"Result":false,"ID":0,"Question":null,"Children":null,"Category":"visualInspection","AnswerNodes":{"True":[4],"False":[5]},"Type":"yesNo","CategoryText":"Sichtprüfung"}
当我尝试使用以下代码对其进行解码时,除AnswerNodes字典外,所有值都被填充。总是变为空:
JsonConvert.DeserializeObject<YesNoTreeNode>(node.NodeOptionsJSON);
// This is a workaround:
if (ret.AnswerNodes is null)
ret.AnswerNodes = JObject.Parse(node.NodeOptionsJSON)["AnswerNodes"].ToObject<Dictionary<object, List<int>>>();
即使在以下测试方案中,它也不起作用。因此,我可以除外,这是由于JSON代码格式错误造成的。
ret = loadFromJSON ? JsonConvert.DeserializeObject<YesNoTreeNode>(node.NodeOptionsJSON) : new YesNoTreeNode();
// At this point, ret.AnswerNodes is null
ret.AnswerNodes = new Dictionary<object, List<int>>();
ret.AnswerNodes.Add(1, new List<int>() { 4 });
ret.AnswerNodes.Add(2, new List<int>() { 5 });
var test = JsonConvert.SerializeObject(ret);
var test2 = JsonConvert.DeserializeObject<YesNoTreeNode>(test);
首先有没有办法使DeserializeObject方法正确解码对象?
答案 0 :(得分:2)
未设置任何属性,因为其设置器为internal set;
。这意味着它们对其他程序集(例如Json.NET)不可见。
Linqpad中的以下代码:
public enum QuestionCategories
{
None,
visualInspection
}
public abstract partial class ClientTreeNode {
public int ID { get; internal set; }
public string Question { get; internal set; }
public List<ClientTreeNode> Children { get; internal set; }
public QuestionCategories Category { get; internal set; }
public Dictionary<object, int[]> AnswerNodes { get; internal set; }
}
public class YesNoTreeNode : ClientTreeNode {
public bool Result { get; internal set; }
}
void Main()
{
var json="{'Result':false,'ID':0,'Question':null,'Children':null,'Category':'visualInspection','AnswerNodes':{'True':[4],'False':[5]},'Type':'yesNo','CategoryText':'Sichtprüfung'}";
var obj=JsonConvert.DeserializeObject<YesNoTreeNode>(json);
JsonConvert.SerializeObject(obj).Dump();
}
产生:
{ "Result":false,
"ID":0,
"Question":null,
"Children":null,
"Category":0,
"AnswerNodes":null
}
删除internal
会产生预期的结果:
{ "Result":false,
"ID":0,"Question":null,"Children":null,"Category":1,
"AnswerNodes":{"True":[4],"False":[5]}
}
默认情况下,Json.NET仅设置公共属性。
如果属性用JsonProperty
属性标记,则可以使用内部设置器,甚至私有设置器:
public abstract partial class ClientTreeNode {
[JsonProperty]
public int ID { get; private set; }
[JsonProperty]
public string Question { get; private set; }
[JsonProperty]
public List<ClientTreeNode> Children { get; private set; }
[JsonProperty]
public QuestionCategories Category { get; private set; }
[JsonProperty]
public Dictionary<object, int[]> AnswerNodes { get; private set; }
}