我有一些包含有點奇怪格式的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