【发布时间】:2017-11-20 14:52:30
【问题描述】:
我重新发布此问题是因为有人将其标记为重复但事实并非如此,因此我详细说明了以避免混淆。
我正在 c# 中创建一个 API,我的 WebApp 可以访问该 API 以获取一些数据。在我的网络应用程序中,我有一个包含(比方说)产品列表的视图。现在我有一条路线可以返回我存储在数据库中的所有产品。
我现在想为 web 应用添加制作复杂过滤器的功能。例如,我希望能够在 webApp 或 Postman 中使用名为“filters”的 URlParam 到达我的路线(比方说)“/api/product”,该 URlParam 将包含 webapp 需要应用的所有过滤器。
现在回到我的 WebApp(使用 Angular 构建),我有一个可以像过滤器树一样创建的服务(请参阅下面的类架构)。 (是的,这种架构可以改进)
我的想法是我可以像这样构建过滤器:如果我想获取名称中包含“foo”且价格超过 15 美元的所有产品:
let filter = new AndNode();
filter.Add(new LikeNode("name", "foo"));
filter.Add(new GTNode("price", 15));
filter.generateJson();
会产生这个Json:
{
"$and": [
{
"$like": { "key": "name", "value": "foo" }
},
{
"$gt": { "key": "price", "value": 15 }
}
]
}
现在,这个 Json 有 1 个要求:它不应该在第一级包含多个属性。因为这是用来生成 SQL 过滤器的,所以 json 必须在他的第一级上只包含一个节点:一个 EQ、LIKE、GT 或 LT 节点,或者如果我们有多个过滤器一个 AND / OR 节点,定义下一级的每个过滤器之间的逻辑“连接”。
所以这是有道理的:
{
"$like": { "key": "name", "value": "foo" }
}
是有效的并且可能导致这个 SQL 语句:
SELECT * FROM products WHERE name LIKE "%foo%";
还有:
{
"$and": [
{
"$like": { "key": "name", "value": "foo" }
},
{
"$gt": { "key": "price", "value": 15 }
}
]
}
是有效的,可能会导致这个 sql 语句:
SELECT * FROM products WHERE name LIKE "%foo%" AND price > 15;
但是:
{
"$like": { "key": "name", "value": "foo" },
"$eq": { "key": "price", "value": 5 },
}
无效,因为它会产生一条这条 sql 语句:
SELECT * FROM products WHERE name LIKE "%foo%" price > 15
Witch 无效,因为缺少 AND 或 OR 关键字。
我想做的事: 在一个美丽的世界里,我希望能够在我的网络应用程序中序列化这个 json,将其转换为有效的 URL 参数字符串,并将其发送到 API (c#) 反序列化该 JSON 以获得与我相同的对象结构在 Web 应用程序上。 对于我们的带有价格和名称的示例,我想要一个 AndNode 类的实例,它的成员“child”包含 2 个对象:LikeNode 类的 1 个实例和 GTNode 类的 1 个实例。
这个实现可能值得商榷,但这是我们现在需要的。
现在,我有:
public class EQNode
{
[JsonProperty("key")]
public string key { get; set; }
[JsonProperty("value")]
public int value { get; set; }
}
public class LikeNode
{
[JsonProperty("key")]
public string key { get; set; }
[JsonProperty("value")]
public string value { get; set; }
}
public class GTNode
{
[JsonProperty("key")]
public string key { get; set; }
[JsonProperty("value")]
public int value { get; set; }
}
public class LTNode
{
[JsonProperty("key")]
public string key { get; set; }
[JsonProperty("value")]
public int value { get; set; }
}
public class OrNode
{
[JsonProperty("$eq")]
public EQNode eq { get; set; }
}
public class AndNode
{
[JsonProperty("$eq")]
public EQNode eq { get; set; }
[JsonProperty("$like")]
public LikeNode like { get; set; }
[JsonProperty("$gt")]
public GTNode gt { get; set; }
[JsonProperty("$lt")]
public LTNode lt { get; set; }
[JsonProperty("$or")]
public List<OrNode> or { get; set; }
[JsonProperty("$and")]
public List<OrNode> and { get; set; }
}
public class RootObject
{
[JsonProperty("$and")]
public List<AndNode> and { get; set; }
[JsonProperty("$or")]
public List<OrNode> or { get; set; }
[JsonProperty("$eq")]
public EQNode eq { get; set; }
[JsonProperty("$like")]
public LikeNode like { get; set; }
[JsonProperty("$gt")]
public GTNode gt { get; set; }
[JsonProperty("$lt")]
public LTNode lt { get; set; }
}
这是由 Visual Studio 的“过去的特殊”功能生成的(我添加了所有 JsonProperty 装饰器以匹配我的 json 中的名称)。 它有效,但是,这并不是我所期望的。
首先,我想拥有与我的 WebApp 结构最接近的结构(具有继承)。 其次,我不喜欢这个生成的代码处理我的根对象中可以有 $eq、$gt、$lt、$like、$or 或 $and 节点的方式,我不敢相信有没有办法有这样一个干净的结构: (注意:这是例如一些使用的装饰器不存在或使用不当的目的,这只是为了演示)
public class RootObject {
public FilterNode root;
}
public class FilterNode {
}
public class ConjunctionNode: FilterNode {
public FilterNode[] childs
}
[JsonObject("$and")]
public class AndNode: ConjunctionNode {
}
[JsonObject("$or")]
public class OrNode: ConjunctionNode {
}
[JsonObject("$like")]
public class LikeNode: FilterNode {
public string key;
public string value;
}
[JsonObject("$eq")]
public class EQNode: FilterNode {
public string key;
public string value;
}
[JsonObject("$gt")]
public class GTNode: FilterNode {
public string key;
public string value;
}
[JsonObject("$lt")]
public class LTNode: FilterNode {
public string key;
public string value;
}
所以,如果我们使用示例 json :
{
"$and": [
{
"$like": { "key": "name", "value": "foo" }
},
{
"$gt": { "key": "price", "value": 15 }
}
]
}
我可以使用:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(filters);
以RootObject的“根”成员作为AndNode的一个实例。 这个 AndNode 将包含这个子数组中的两个对象,它们是 LikeNode 的一个实例和 GTNode 的一个实例。
这个可以吗?
【问题讨论】:
-
您最初问题的答案有什么问题?
-
我原来的帖子不太详细。但是有回应:使用“过去的特殊功能”是一个很好的建议,而其他答案是让我详细说明。所以现在我现在有答案来解决这个问题。
-
您应该更新初始问题,而不是发布新问题。 @angsuman-ray 还要求提供详细的 JSON,从外观上看,您还没有回复他们。
-
我在回答他们之后立即编辑了我的帖子,我会这样做。我的更新位于“编辑 1:”下方。这是在编辑我的帖子之后,我看到帖子被“锁定”(重复)。此外,我的问题的两个版本之间的帖子令人困惑。我决定用(我希望)更清楚的解释重新打字。我将在我的旧帖子中引用这篇文章并要求关闭我的第一个
标签: c# .net json deserialization