我有一些包含有点奇怪格式的JSON文件。我必须阅读,修改和保存我的项目的这种格式。不幸的是,我对给定的格式没有任何影响。有选择地将实例的属性序列化为JSON
这种格式的奇怪之处在于,这个结构中的所有实体都有一个唯一的标识符,它被无效地称为“$ id”。这些实例也可以通过它们的id来引用,而不是完整的属性集。在这种情况下,没有“$ id”,而是有一个“$ ref”字段,其中包含一个已经定义的实体。看看下面的(缩短)例如:
{
"$id": "1",
"StyleName": "Standard",
"Style": {
"$id": "2",
"ShapeStyle": {
"$id": "3",
"Background": {
"$id": "4",
"Color": {
"$id": "5",
"A": 255,
"R": 68,
"G": 84,
"B": 106
}
}
},
"RightEndCapsStyle": {
"$id": "6",
"Background": {
"$id": "7",
"Color": {
"$ref": "5"
}
}
}
}
}
为了解决这个问题,我创建了一个C#基类实体所有JSON数据类。这个基类维护一个ID的注册表,以便它可以很容易地找到一个给定的实例$ ref。下面的代码:
public class Entity
{
public static Dictionary<string, Entity> Registry = new Dictionary<string, Entity>();
private string key = string.Empty;
[JsonProperty("$id", Order = -2)]
[DefaultValue("")]
public string Key
{
get { return key; }
set
{
key = value;
if (!string.IsNullOrEmpty(key)) Registry.Add(key, this);
}
}
[JsonProperty("$ref")]
public string RefKey { get; set; }
[JsonIgnore]
public bool IsReference => !string.IsNullOrEmpty(RefKey);
[JsonIgnore]
public Entity RefEntity
{
get
{
Entity entity = null;
if (IsReference && !Registry.TryGetValue(RefKey, out entity))
{
throw new ApplicationException("Referenced entity not found!");
}
return entity;
}
}
}
的JSON类hiearchy看起来是这样的:
public class RootObject: Entity
{
public string StyleName { get; set; }
public StyleRoot Style { get; set; }
}
public class StyleRoot: Entity
{
public Style ShapeStyle { get; set; }
public Style RightEndCapsStyle { get; set; }
}
public class Style: Entity
{
public Background Background { get; set; }
}
public class Background: Entity
{
public Color Color { get; set; }
}
public class Color: Entity
{
public int A { get; set; }
public int R { get; set; }
public int G { get; set; }
public int B { get; set; }
}
到目前为止,一切都很好。现在我的问题:
[JsonProperty("$id")]
和[JsonProperty("$ref")]
不工作,因为的$ id和$裁判没有有效的JSON字段名标识符。目前,我正在使用正则表达式将其替换为有效的内容,然后将它们重新替换为之前的内容。但是,这是缓慢的。我想知道是否可以使用NamingStrategy
来达到同样的效果。但我没有成功。记住,我需要两种方式,反序列化和序列化。- 序列化是一个更难的问题。如果我按照原样序列化结构,那么在每个实例中,我最终都会得到
"$id":
和"$ref":
字段。更重要的是,与所引用的项目一起,所有其他字段都使用默认值进行序列化。最简单的方法是在JsonSerializerSettings
中简单地设置DefaultValueHandling.IgnoreAndPopulate
。但是这样,所有的默认值都会从输出中剥离,导致意外的行为。我试图用ContractResolver
去,但因为这是当前属性本地,并且不能考虑周围的实体,所以失败了。有没有其他方法来实现自定义序列化策略?
这个问题很难说,我知道。还有很多东西需要阅读和理解。但如果这很容易,我不会花费精力把它放在这里。迫切需要你的帮助。
完美!适用于我。 你对“$ ref”的价值是正确的。我已经剥去了很多文字,使它更加紧凑。我不得不做一些手动编辑... 顺便说一句,PreserveReferenceHandling.Object和PreserveReferenceHandling.All有什么区别? – freefall