首页 > 解决方案 > API 响应:同一响应中的引用是一种不好的做法?

问题描述

多年来,我一直在处理这个请求,这给了我们这样的回应(这是一个许多字段被截断的简短示例):

{
    "catalog": {
        "categories": [
            {
                "id": "firstCategory",
                "name": "The first category!",
                "order": 0,
                "offers": [
                    {
                        "id": "offer1" // a LOT of fields
                    },
                    {
                        "id": "offer2" // a LOT of fields
                    },
                    {
                        "id": "offer3" // a LOT of fields
                    }
                ]
            },
            {
                "id": "secondCategory",
                "name": "The second category!",
                "order": 0,
                "offers": [
                    {
                        "id": "offer2" // a LOT of fields ... same again
                    },
                    {
                        "id": "offer3" // a LOT of fields ... same again
                    },
                    {
                        "id": "offer4" // a LOT of fields
                    }
                ]
            },
            {
                "id": "thirdCategory",
                "name": "The third category!",
                "order": 0,
                "offers": [
                    {
                        "id": "offer1" // a LOT of fields ... same again
                    },
                    {
                        "id": "offer4" // a LOT of fields ... same again
                    },
                    {
                        "id": "offer5" // a LOT of fields
                    }
                ]
            }
        ]
    }
}

你怎么看,我们有一定数量的类别(在我的每天是 5-15 个)包含一些优惠(10-30 个类别)。很多时候,这些优惠在不同的类别中重复出现:这些优惠完全相同(firstCategory 中 id="offer1" 的优惠与 thirdCategory 中 id="offer1" 的优惠完全相同)。

它经常发生,好像这还不够,一个 Offer 元素包含许多字段(大约 50 ......

我想知道尝试通过这样设置的参考系统来解决问题是否是正确的做法:

{
    "catalog": {
        "categories": [
            {
                "id": "firstCategory",
                "name": "The first category!",
                "order": 0,
                "idOffers": [ "offer1", "offer2", "offer3" ]
            },
            {
                "id": "secondCategory",
                "name": "The second category!",
                "order": 1,
                "idOffers": [ "offer2", "offer3", "offer4" ]
            },
            {
                "id": "thirdCategory",
                "name": "The third category!",
                "order": 2,
                "idOffers": [ "offer1", "offer4", "offer5" ]
            }
        ],
        "offers": [
            {
                "id": "offer1" // a LOT of fields... but written only once
            },
            {
                "id": "offer2" // a LOT of fields... but written only once
            },
            {
                "id": "offer3" // a LOT of fields... but written only once
            },
            {
                "id": "offer4" // a LOT of fields... but written only once
            },
            {
                "id": "offer5" // a LOT of fields... but written only once
            }
        ]
    }
}

虽然它对我来说似乎更实用、更干净,但我想知道的是:这是一种不好的做法吗?

PS:如果有人想知道提出两个类似GET catalog/categoriesGET catalog/{idCategory}/offers 或类似的请求是否更正确,他必须知道由于各种业务和架构原因,所提出的请求必须只保留一个。

标签: jsonapiresponse

解决方案


您的建议本质上没有任何问题;这可能是一个更好的方法。除了减少有效负载大小的明显好处外,您的建议还将消除数据异常的可能性。现有结构中可能会出现异常情况,因为它允许同一报价的两个不同“副本”具有不相符的属性值。如果您不完全信任数据源,那么您可能会觉得需要验证传入的报价。但是您甚至不能这样做,因为您可以将(比如说)offer1 的众多副本中的哪一个视为“主”副本?

正是出于这个原因,Ted Codd 发明了第一范式,通常被概括为“消除重复组”。

我说这可能是一个更好的方法,但它是否真的一个更好的方法取决于你的上下文。例如,如果您想立即将这些数据存储在关系数据库中,那么这绝对是一种更好的方法,因为规范化已被推送到上游,可能会回到源头,但肯定超出了您的应用程序范围,这意味着您不需要不必担心上述异常情况,而且您要处理的数据要少得多。

另一方面,如果您想生成分层报告 - 或将数据存储在类似于您收到的分层结构中,那么它就不是那么明确了。我仍然认为消除异常风险是一个很大的收获,因为有效载荷大小可能会大幅减少,但是您可能会付出代价,因为必须在某处缓存报价,然后必须“查找”报价数据你处理每个idOffers数组。如果性能因此受到严重影响,您可能需要权衡这些事情。如果报价数量相对较少,我怀疑这将是一个问题。

所以我认为你的直觉是正确的。


推荐阅读