我需要使用json格式,通过api调用将python后端中的数据传递给前端。在python后端,数据处于字典结构中,我可以轻松直接地将其转换为json。但我应该吗?
我的前端开发人员认为答案是否定的,原因与最佳实践有关。
但我对此提出质疑:
是最好像python那样构造json,还是应该将它转换为其他形式,比如几个数组(在下面的示例中是必要的)?
或者,换个说法:
与通过jsons接口信息的集合/dicts/映射/数组有关的指导原则应该是什么?
我在谷歌上搜索了一些答案,但我并没有遇到很多直接解决这个问题的方法。链接将不胜感激。
(请注意下面的示例:当然,如果数据是写入数据库的,那么前端直接访问数据库可能是最有意义的,但假设情况并非如此)
示例:
在后端有一个名为pets的对象集合:集合中的每个项都有一个唯一的pet_id、一些非可选属性(例如name和date_of_birth )、一些可选属性( registration_certificate_nr )、adopted_from_kennel (可选属性)、一些列表(如siblings和children )以及一些对象(如medication )。
假设前端在某一时刻需要所有这些信息,它可能是
{
"pets": {
"17-01-24-01": {
"name": "Buster",
"date_of_birth": "04/01/2017",
"registration_certificate_nr": "AAD-1123-1432"
},
"17-03-04-01": {
"name": "Hooch",
"date_of_birth": "05/02/2015",
"adopted_from_kennel": "Pretoria Shire",
"children": [
"17-05-01-01",
"17-05-01-02",
"17-05-01-03"
]
},
"17-05-01-01": {
"name": "Snappy",
"date_of_birth": "17-05-01",
"siblings": [
"17-05-01-02",
"17-05-01-03"
]
},
"17-05-01-02": {
"name": "Gizmo",
"date_of_birth": "17-05-01",
"siblings": [
"17-05-01-01",
"17-05-01-03"
]
},
"17-05-01-03": {
"name": "Toothless",
"date_of_birth": "17-05-01",
"siblings": [
"17-05-01-01",
"17-05-01-03"
],
"medication": [
{
"name": "anti-worm",
"code": "aw445",
"dosage": "1 pill per day"
},
{
"name": "disinfectant",
"code": "pdi-2",
"dosage": "as required"
}
]
}
}
}发布于 2018-06-19 00:50:09
JSON格式在某种程度上是一个主观的问题,相关的分歧通常最好在同事之间解决。
尽管如此,对于问题中的JSON格式仍有一些可能有效的批评,特别是当我们试图创建一个一致的RESTful API时。
突出的两个痛点:
id。问题中提到了一个pet_id,但它似乎与宠物对象本身是分开维护的。如果问题中的pets映射中访问了一个值,则当完整的JSON不再可用时,API的用户必须手动将pet_id添加到提供的宠物对象中,这样才能在行的更远的地方获得可用的id。在这种情况下,我们最接近于指导标准的是休息建筑风格和JSON标准。
我们可以从查看JSON标准开始。以下是JSON wiki的引文
JavaScript语法定义了几种未包含在JSON标准中的原生数据类型: Map、Set、Date、Error、正则表达式、函数、允诺和
undefined。
这里的关键优点是,JSON不是用来表示映射数据类型的。Python字典是一个映射实现,因此直接将字典序列化为JSON,以表示类似于映射的集合,这与JSON的预期使用是背道而驰的。
对于像宠物这样的单个对象,JSON对象是合适的,但是对于集合,有一个选项: JSON数组。在这个答案中有一个JSON数组的用法示例。
在某些边缘情况下,偏离标准是有意义的,但在这种情况下,我看不出有什么原因。
从RESTful设计的角度来看,JSON格式也有一些缺点。RESTful API的设计很好,因为它鼓励人们保持简单和一致。它也恰好是一个事实上的行业标准。
在RESTful HTTP中,获取单个宠物资源的方式如下:
Request: GET /api/pets/17-01-24-01
Response: 200 {
"id": "17-01-24-01",
"name": "Buster",
"date_of_birth": "04/01/2017",
"registration_certificate_nr": "AAD-1123-1432"
}响应是一个具有显式定义id的完全定义的资源。它也是宠物最简单的完整JSON表示形式。
接下来,我们定义了获取多个宠物资源的方式,假设只定义了2个宠物:
Request: GET /api/pets
Response: 200 [
{
"id": "17-01-24-01",
"name": "Buster",
"date_of_birth": "04/01/2017",
"registration_certificate_nr": "AAD-1123-1432"
},
{
"id": "17-03-04-01",
"name": "Hooch",
"date_of_birth": "05/02/2015",
"adopted_from_kennel": "Pretoria Shire",
"children": [
"17-05-01-01",
"17-05-01-02",
"17-05-01-03"
]
}
]上述响应格式是使单个资源响应格式多元化的最直接的方式,从而使API尽可能简单和一致。(为了简洁起见,我只使用了问题中的两个示例资源)。再次,id是显式定义的,并且属于它们各自的宠物对象。
将地图键添加到上面的格式是没有好处的。
问题中JSON格式的支持者可能建议将id字段添加到每个宠物对象中,以便在痛点2附近工作,但这会引起在响应中重复数据的问题。为什么id需要同时位于对象的内部和外部?它肯定只应该在里面?在消除冗余数据之后,结果将类似于上面的响应。
这就是剩下的论点。在有些用例中,REST不起作用,但这与此相去甚远。
PS。前端不应该直接访问数据库。API负责编写和读取所使用的任何数据持久性基础结构。在许多更大的现实系统中,前端和API之间甚至还有一个额外的BFF层,将前端和DB进一步分离开来。
https://stackoverflow.com/questions/50910638
复制相似问题