[英]Deserializing JSON with an unknown number of nested arrays representing a query
我有一些JSON,如下所示。
{
"queryEntry": [
[
{
"type": "expression",
"key": "Account.Name",
"operators": "=",
"value": "asd"
}
],
{
"type": "conjunction",
"value": "OR",
"key": null,
"operators": null
},
[
{
"type": "expression",
"key": "Account.TotalEmployees",
"operators": "=",
"value": "123"
},
{
"type": "conjunction",
"value": "AND",
"key": null,
"operators": null
},
[
{
"type": "expression",
"key": "Account.LastYearRevenue",
"operators": "=",
"value": "123"
},
{
"type": "conjunction",
"value": "OR",
"key": null,
"operators": null
},
[
{
"type": "expression",
"key": "Account.Last5YearRevenue",
"operators": "=",
"value": "123"
}
]
]
],
{
"type": "conjunction",
"value": "AND",
"key": null,
"operators": null
},
[
{
"type": "expression",
"key": "Account.OwnerName",
"operators": "=",
"value": "asd"
}
]
]
}
這實際上是我們從jQuery生成的SQL中的where
條件。 我必須將此字符串反序列化為C#中的類。
任何人都可以指導我為什么要創建這個類來反序列化這個? 此外,不知道嵌套數組有多深。
這是一種難以使用的JSON格式,因為它是一種遞歸數組結構,其中數組可以包含對象或數組或兩者的組合。 我可以看到JSON對象表示查詢的各個部分,但查詢子表達式不在我想要的對象內。 相反,似乎數組被用作文字括號來分組查詢!
我認為將其反序列化為中間合理類結構的最佳方法是使用Composite模式 ,其中一個類既代表查詢的單個部分(即表達式或連接),也表示相同的分組。 像這樣的東西:
class QueryEntry
{
public string Type { get; set; }
public string Key { get; set; }
public string Operators { get; set; }
public string Value { get; set; }
public List<QueryEntry> Group { get; private set; }
public bool IsGroup { get { return Group.Count > 0; } }
public QueryEntry()
{
Group = new List<QueryEntry>();
}
}
我們還需要一個包裝類來處理JSON根目錄下的queryEntry
屬性:
class RootObject
{
public QueryEntry QueryEntry { get; set; }
}
現在,既然JSON可以是任何級別的對象或異構數組,我們不能只在Json.Net上拋出這個類,並期望它在門外正確地反序列化。 (您正在使用Json.Net ?你不是你的問題沒有說)。我們將需要使用自定義JsonConverter
到JSON結構翻譯成復合類結構:
class QueryEntryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(QueryEntry);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
QueryEntry entry = new QueryEntry();
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
serializer.Populate(token.CreateReader(), entry);
}
else if (token.Type == JTokenType.Array)
{
foreach (JToken child in token)
{
entry.Group.Add(child.ToObject<QueryEntry>(serializer));
}
}
return entry;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要反序列化,我們可以將轉換DeserializeObject<T>
的實例傳遞給DeserializeObject<T>
如下所示:
var root = JsonConvert.DeserializeObject<RootObject>(json, new QueryEntryConverter());
最后,如果我們想將反序列化的查詢表達式樹轉換為可讀的字符串,我們需要在QueryEntry
類上使用遞歸的ToString()
方法:
public override string ToString()
{
if (IsGroup)
{
StringBuilder sb = new StringBuilder();
sb.Append('(');
foreach (QueryEntry entry in Group)
{
sb.Append(entry.ToString());
}
sb.Append(')');
return sb.ToString();
}
else if (Type == "expression")
{
return Key + ' ' + Operators + ' ' + Value;
}
else if (Type == "conjunction")
{
return ' ' + Value + ' ';
}
return string.Empty;
}
然后我們可以這樣做:
Console.WriteLine(root.QueryEntry.ToString());
在您的問題中使用JSON,輸出將是:
((Account.Name = asd)OR(Account.TotalEmployees = 123 AND(Account.LastYearRevenue = 123 OR(Account.Last5YearRevenue = 123)))AND(Account.OwnerName = asd))
這是一個有效的演示: https : //dotnetfiddle.net/D3eu5J
您可以使用JsonConvert進行隱蔽,如下所示
MyData tmp = JsonConvert.DeserializeObject<MyData>(json);
foreach (string typeStr in tmp.type[0])
{
// Do something with typeStr
}
如果您希望對類屬性使用[jsonproperty]注釋,則可以在屬性中將類創建為字段
class MyData
{
@JsonProperty("t")
公共字符串t; 公共布爾
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.