我有一些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"
}
]
]
}
这实际上是SQL中的where
条件,我们从jQuery生成它。我必须将此字符串反序列化为C#中的类。
任何人都可以指导我为了反序列化这个类而创建的类吗?此外,不知道嵌套数组有多深。
答案 0 :(得分:3)
这是一种难以使用的JSON格式,因为它是一种递归数组结构,其中数组可以包含对象或数组或两者的组合。我可以看到JSON对象表示查询的各个部分,但查询子表达式不在我想要的对象内。相反,似乎数组被用作文字括号来分组查询!
我认为将其反序列化为中间理智类结构的最佳方法是使用Composite pattern,其中一个类既代表查询的单个部分(即表达式或连接),也代表分组一样的。像这样:
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>
,如下所示:
var root = JsonConvert.DeserializeObject<RootObject>(json, new QueryEntryConverter());
最后,如果我们想将反序列化的查询表达式树转换为可读的字符串,我们需要在ToString()
类上使用递归QueryEntry
方法:
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
答案 1 :(得分:-1)
您可以使用JsonConvert进行隐身,如下所示
MyData tmp = JsonConvert.DeserializeObject<MyData>(json);
foreach (string typeStr in tmp.type[0])
{
// Do something with typeStr
}
如果您希望对类属性使用[jsonproperty]注释,可能会在属性中将类创建为字段
class MyData
{
@JsonProperty("t")
public string t; public bool a;
}