【问题标题】:How to represent combination data in JSON?如何在 JSON 中表示组合数据?
【发布时间】:2021-12-28 16:13:38
【问题描述】:

我正在实现一个 API,它返回有多少用户正在使用特定的应用程序。

例如,假设我要返回的数据表明

10 人只使用 App1,8 人只使用 App2,8 人只使用 App3,15 人同时使用 App1 和 App2,20 人全部使用 App1、App2 和 App3。

我们如何设计 JSON 中的响应结构?

我想以逗号分隔的格式返回它

{
  "App1": 10,
  "App2": 8,
  "App3": 8,
  "App1,App2": 15,
  "App1,App2,App3": 20
}

这种格式是否正确且语义正确?

我也想到了数组,

[
   {"key": ["App1"], "count": 10},
   {"key": ["App2"], "count": 8},
   {"key": ["App3"], "count": 8},
   {"key": ["App1", "App2"], "count": 15},
   {"key": ["App1", "App2", "App3"], "count": 20}
]

但对它在语义上是否正确表示怀疑。

有没有更好的方法?表示这些数据的最佳方式是什么?

【问题讨论】:

    标签: node.js json spring api-design


    【解决方案1】:

    我认为您尝试过的解决方案非常有限。您的解决方案适用于 3 个应用程序,但假设您稍后想要添加更多应用程序,然后您也添加了这些返回类型。

    我想建议如下。此建议耦合度低,适用于任意数量的应用

    {
      "IndividualAppUsersCount":[10,8,8],
      "MultipleAppUsersCount":[ 
        {
          "AppsInUse":"App1+App2",
          "Count":15
        },
        {
          "AppsInUse":"App1+App2+App3",
          "Count":20
        }
      ]
    }
    

    使用这种方法的好处是您不限于预定义的应用程序,而是可以轻松地为 0 到 n 个应用程序工作。只需循环遍历数组,得到相应的结果。

    您甚至可以通过以下方式改善上述结果。

    {
    
      "AppUsersCount":[
        {
          "AppsInUse":"App1",
          "Count":10
        },
        {
          "AppsInUse":"App2",
          "Count":8
        },
        {
          "AppsInUse":"App3",
          "Count":8
        },
        {
          "AppsInUse":"App1, App2",
          "Count":15
        },
        {
          "AppsInUse":"App1, App2, App3",
          "Count":20
        }
      ]
    }
    

    我希望这能回答您的问题。但是,如果您还有其他问题,请告诉我,我很乐意回答。

    感谢您的阅读。

    【讨论】:

    • @ramiz 无法理解您为什么说我的回答有限。我已经给出了一个使用 3 个应用程序的示例,就像您在答案中给出的方式一样。明天有更多应用程序时,添加另一个以逗号分隔的键没有问题。没有任何耦合。
    • 嗨@Aniket,很高兴你问到。您的代码是正确的,但我不建议这样做,因为随着代码的增长将难以管理。我的意思是,当您尝试解析 JSON 时,您必须专门读取这些键(即“App1”、“App2”等)。因此,如果您添加一个新键(即“App_n”),那么您也必须在代码中添加该逻辑。希望您现在了解痛点,否则请告诉我。
    【解决方案2】:

    我会采用以下结构:

    {
      "usersCount": [
        {
          "apps": ["App1"],
          "userCount": 10
        },
        {
          "apps": ["App2"],
          "userCount": 8
        },
        {
          "apps": ["App3"],
          "userCount": 8
        },
        {
          "apps": ["App1", "App2"],
          "userCount": 15
        },
        {
          "apps": ["App1", "App2", "App3"],
          "userCount": 20
        }
      ]
    }
    

    这将使解析和处理多个应用程序变得更容易(例如,与字符串拆分相比)。为了使它的类型更强一点,我将使用App 枚举的App1App2App3 值。

    【讨论】:

    • @Aniket,您对我的回答有任何疑问吗?是不是不清楚或遗漏了什么?
    【解决方案3】:

    将此问题视为维恩图中的三个重叠总体。表示维恩图的最佳方式是将每个部分表示为成分的有序列表以及与之关联的数字。这将唯一地代表每个部分以构成一个整体。

    现在,这两种解决方案都实现了这一目标。但是作为 JSON 键的 CSV 有几个缺陷:

    1. Typescript 定义会很困难。在第一种情况下,您的 Typescript 定义将是 Record<string, number>,它不像第二种情况那样强类型(阅读较少的特异性),即

      type App = 'App1' | 'App2' | 'App3';
      type AppUsage = Array<{ key: Array<App>, count: number }>;
      
    2. 第一种是脆的。如果应用名称有逗号怎么办?您的客户必须知道格式。他们如何区分"App1,App2""App1, App2"(注意逗号后面的空格?)。通常建议不要使用与格式相关的标识符。数组更易于使用并提供更好的一致性。

    3. 如果您使用 GraphQL,则使用普通的JSON(这是第一种方法)通常被认为是一种不好的做法。

    所以,底线应该是更好的方法,

    
    type App = 'App1' | 'App2' | 'App3';
    type AppUsage = Array<{ key: Array<App>, count: number }>;
    
    const appUsage: AppUsage = [
       {"key": ["App1"], "count": 10},
       {"key": ["App2"], "count": 8},
       {"key": ["App3"], "count": 8},
       {"key": ["App1", "App2"], "count": 15},
       {"key": ["App1", "App2", "App3"], "count": 20}
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 2019-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-28
      • 1970-01-01
      相关资源
      最近更新 更多