分层数据的平面或嵌套JSON?


12

我已经来回切换了约5次。这个REST端点/api/tags/仅供内部使用(没有第三方客户端),我是唯一使用它的人。

我要在这两种表示形式之间做出决定:

平面

{  
   "types":[  
      {  
         "id":1,
         "text":"Utility"
      },
      {  
         "id":7,
         "text":"Lease Terms"
      },
   ],
   "tags":[
      {  
         "id":8,
         "text":"Water",
         "type":1
      },
      {  
         "id":9,
         "text":"Electricity",
         "type":1
      },
      {  
         "id":5,
         "text":"Minimum 12 month lease",
         "type":7
      },
      {  
         "id":17,
         "text":"lease negotiable/flexible",
         "type":7
      },
   ]
}
  • 它有点模块化。可以添加另一个顶层,例如“国家/地区”而不会破坏兼容性。

巢状

{  
   "1":{  
      "text":"Utility",
      "tags":{  
         "8":{  
            "text":"Water"
         },
         "9":{  
            "text":"Electricity"
         },
      }
   },
   "2":{  
      "text":"Lease Terms",
      "tags":{  
         "5":{  
            "text":"Minimum 12 month lease"
         },
         "17":{  
            "text":"lease negotiable/flexible"
         },
      }
   },
}
  • 它已经是可用格式了。使用数据之前不需要遍历数据。
  • 节省一些带宽。即使在使用gzip之后,它也会稍小一些。

应该使用哪一个,为什么?如果这是个人喜好问题,那么经验丰富的开发人员将首选哪种代表方式,为什么?


Is this a matter of personal preference?。我想是这样。需求>需求>首选项
Laiv

1
@Laiv在这种情况下,我的问题应改写为“经验丰富的开发人员更喜欢哪种代表,为什么?”
dvtan

这些ID随时间推移是否稳定,可以让客户端记住并稍后使用,还是只是在本地发送消息?
Erik Eidt

@ErikEidt它们是永久的数据库主键。
dvtan

您是否将Water视为Utility的子类,还是作为Utility的实例?
Erik Eidt

Answers:


8

取决于您的用例。

当将JSON与statica类型的语言一起使用时,如果您的结构映射到您的类型,则将获得巨大的收益。这意味着应该预先知道所有键的名称。

因此,如果您打算使用Java来使用该服务,或者计划使用JSON Schema对其进行文档化,那么第一号将更为简洁(当然两者都可以使用)。


4

没有更多的背景很难说。我曾与两者一起工作,但逐渐地我开始倾向于#1。总的来说,我发现简单性比复杂性更重要。

在#1中,实体和关系清晰明了,而#2需要不同的思维方式。对于某些人来说,树(作为数据结构)并不是自我描述。想想那些初级开发人员,他们几乎看不到比Person> Address更深的汇总。

我可以将#1读为:

  • 有一个类型化标签的集合

但是,我们如何仅用7个词来描述#2?如果我不熟悉树结构,则可以将#2阅读为

  • 标签有两个属性5和17,但我不知道它们的类型。无论类型是什么,都有一个属性text

不要误会我的意思,#2可能是一个聪明的解决方案,但是我不会为了聪明(或效率)而不必要地牺牲可读性。

在撰写此答案时,我正在一个需要与第三方服务集成的项目,该服务的响应与#2非常相似。该服务为我们提供了日历:年,月,日和一天中的小时

 { "2017" : { "01": { "01" : ["00:00", "01:00", "02:00"] } } } 

作为我的Java开发人员,对服务响应的反序列化最终导致了可读性很强的代码,因为没有直接通过getters | setters | constructor映射到类的过程。相反,我不得不遍历文档(getNode,getSiblings,getNodeName,getChildAsText,isNodeObject,isText等)并手动填充类的层次结构。最终,我设法将数字树映射到时间戳集合中!您会说哪种结构更易于阅读和反序列化?如果您在客户端,您想获得哪一个?


1

如果您不想要其他任何东西,则可以使用:

{
    "Utility": {
        "8": "Water",
        "9": "Electricity"
     },
     "Lease Terms": {
        "5": "Minimum 12 month lease",
        "17": "lease negotiable/flexible"
     }
}

不幸的是,JSON仅允许字符串作为键。


或潜在"Utility": ["Water","Electricity"]等等
Caleth

但是,那么您将无法引用它们。我希望所有这些后面都有一个描述数千所房屋的数组,每个房屋都包含例如“ 8”,“ 9”,“ 5”。
gnasher729
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.