【问题标题】:Referencing another class within a class for json为 json 引用一个类中的另一个类
【发布时间】:2014-07-13 01:35:18
【问题描述】:

在我的服务类构造函数中,我填充了两个存储库:

private List<BackupRule> rules;
private List<BackupPath> paths;

public RuleService()
{
  List<BackupRule> _rules = new List<BackupRule>();
  List<BackupPath> _paths = new List<BackupPath>();
  using (var wc = new System.Net.WebClient())
  {
    string json = wc.DownloadString(jsonRuleFile);
    if (json.Length > 0)
    {
      _rules = JsonConvert.DeserializeObject<List<BackupRule>>(json);
      _paths = JsonConvert.DeserializeObject<List<BackupPath>>(json);
    }
  }
  rules = _rules;
  paths = _paths;
}

然后我尝试创建规则并将规则添加到存储库:

创建规则的代码

IRuleService db = new RuleService();
List<BackupPath> paths = new List<BackupPath>();
paths.Add(new BackupPath { Type = PathType.Source, Value = "C:\\Test\\" });
paths.Add(new BackupPath { Type = PathType.Destination, Value = "C:\\Test\\" });
paths.Add(new BackupPath { Type = PathType.Source, Value = "C:\\Test\\" });
paths.Add(new BackupPath { Type = PathType.Source, Value = "C:\\Test\\" });
BackupRule rule1 = new BackupRule() { Name = "test1", Type = RuleType.Archive, UserName = System.Environment.UserName, Paths = paths, EndOfDay = true, Created = DateTime.Now};
BackupRule rule2 = new BackupRule() { Name = "test2", Type = RuleType.Archive, UserName = System.Environment.UserName, Paths = paths, EndOfDay = true, Created = DateTime.Now };
db.CreateRule(rule1);
db.CreateRule(rule2);
db.SaveChanges();

将规则添加到存储库的接口方法

public BackupRule CreateRule(BackupRule rule)
{
  if (rules.Any(r => r.Name == rule.Name))
  {
    return null;
  }
  rule.Paths = rule.Paths.OrderBy(p => p.Type.GetHashCode()).ToList();
  foreach (BackupPath path in rule.Paths)
  {
    path.Id = (paths.Count() == 0) ? 1 : paths.LastOrDefault().Id + 1;
    paths.Add(path);
  }
  rule.Id = (rules.Count() == 0) ? 1 : rules.LastOrDefault().Id + 1;
  rules.Add(rule);
  rules = rules.OrderBy(r => r.Id).ToList();
  return rule;
}

将(原文如此?)序列化回 json 的接口方法

public void SaveChanges()
{
  using (FileStream fileStream = File.Open(@jsonRuleFile, FileMode.OpenOrCreate))
  using (StreamWriter streamWriter = new StreamWriter(fileStream))
  using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
  {
    jsonWriter.Formatting = Formatting.Indented;

    JsonSerializer serializer = new JsonSerializer();
    serializer.Serialize(jsonWriter, rules);
    serializer.Serialize(jsonWriter, paths);
  }
}

json 输出

[
  {
    "Id": 1,
    "Name": "test1",
    "UserName": "Aaron",
    "rule_type": "Archive",
    "Paths": [
      {
        "$id": "1",
        "Id": 5,
        "Value": "C:\\Test\\",
        "Type": "Source"
      },
      {
        "$id": "2",
        "Id": 6,
        "Value": "C:\\Test\\",
        "Type": "Source"
      },
      {
        "$id": "3",
        "Id": 7,
        "Value": "C:\\Test\\",
        "Type": "Source"
      },
      {
        "$id": "4",
        "Id": 8,
        "Value": "C:\\Test\\",
        "Type": "Destination"
      }
    ],
    "EndOfDay": true,
    "Created": "2014-07-12T20:14:03.9126784-05:00"
  },
  {
    "Id": 2,
    "Name": "test2",
    "UserName": "Aaron",
    "rule_type": "Archive",
    "Paths": [
      {
        "$ref": "1"
      },
      {
        "$ref": "2"
      },
      {
        "$ref": "3"
      },
      {
        "$ref": "4"
      }
    ],
    "EndOfDay": true,
    "Created": "2014-07-12T20:14:03.9126784-05:00"
  }
][
  {
    "Id": 5,
    "Value": "C:\\Test\\",
    "Type": "Source"
  },
  {
    "Id": 6,
    "Value": "C:\\Test\\",
    "Type": "Source"
  },
  {
    "Id": 7,
    "Value": "C:\\Test\\",
    "Type": "Source"
  },
  {
    "Id": 8,
    "Value": "C:\\Test\\",
    "Type": "Destination"
  },
  {
    "Id": 5,
    "Value": "C:\\Test\\",
    "Type": "Source"
  },
  {
    "Id": 6,
    "Value": "C:\\Test\\",
    "Type": "Source"
  },
  {
    "Id": 7,
    "Value": "C:\\Test\\",
    "Type": "Source"
  },
  {
    "Id": 8,
    "Value": "C:\\Test\\",
    "Type": "Destination"
  }
]

正在序列化的类

// using statements added to post to help 
// reader understand I am using Json.Net
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class BackupRule
{
  [JsonProperty]
  public int Id { get; set; }
  [JsonProperty]
  public string Name { get; set; }
  public string UserName { get; set; }
  [JsonProperty(PropertyName = "rule_type")]
  [JsonConverter(typeof(StringEnumConverter))]
  public RuleType Type { get; set; }
  [JsonProperty(ItemIsReference = true)]
  public List<BackupPath> Paths { get; set; }
  public bool EndOfDay { get; set; }
  public DateTime Created { get; set; }
}
public class BackupPath
{
  public int Id { get; set; }
  public string Value { get; set; }
  [JsonConverter(typeof(StringEnumConverter))]
  public PathType Type { get; set; }
}

问题是 json 甚至不是它给我的正确格式:

警告 1 JSON 文档中只允许有一个顶级数组或对象。

它实际上并没有引用序列化的BackupPath 类,它只是引用在其他BackupRule 对象中创建的其他BackupPaths。我在这里哪里做错了?理想情况下,我希望它从列表中创建两个“表”并让BackupRule 引用BackupPaths“表”,就像它在第二个BackupRule 示例中所做的那样,而不是BackupRule #2 引用@ 987654334@ 存储在BackupRule #1 我宁愿都引用序列化的BackupPath“表”。理想情况下,我想将两个序列化列表都存储在一个 json 文件中,但我对此很灵活。

【问题讨论】:

    标签: c# asp.net json serialization json.net


    【解决方案1】:

    至于警告,那是因为你有这个:

    serializer.Serialize(jsonWriter, rules);
    serializer.Serialize(jsonWriter, paths);
    

    正如警告所说,JSON 真的只能有 1 个顶级元素,而您已经编写了 2 个顶级元素。为了使警告消失,您可以将 rulespaths 包装到一个对象中:

    serializer.Serialize(jsonWriter, new {Rules = rules, Paths = paths});

    【讨论】:

    • 这实际上完全解决了问题。只要我先序列化路径,规则就会引用路径:serializer.Serialize(jsonWriter, new {Paths = paths, Rules = rules}); 在我将你的答案标记为答案之前,我会等着看其他人是否用更稳定/更有效的解决方案来回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多