一直以来有个疑问,之前公司的 ios 开发要求我的接口给出的数组数据不要是对象,说处理不了,不能处理. 举例,本人 PHPer,我通常自己用的数组都是带下标转的,例如 { "100":{ "id":100 "title":"xxx" }, "105":{ "id":105 "title":"sss" } } 当我已知 id 是 105 的情况下我就可以直接 $array[105][title]取数据了.当我需要渲染数据的时候我就直接 foreach,数组的下标似乎对我没有任何影响. 但公司的 ios 说上面的处理不了,对数据提出以下要求,一定要下面这种常规的数组形式,而不是对象形式 [ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ] 不明白处理上有啥不同?还是有什么说法?
这个异议的数据接口呢,之前给前端用的(前端没有对数据格式提出过异议),刚好那天app按需求也需要这个接口,前端就直接给到app那边了,app那边觉得数据格式不行,就来找我修正了(按app请求来源转换了需要的格式,前端仍然使用原先的格式),app没跟我讲清楚个所以然,但我当时就改了,我只是觉得有点疑问,就来问问.
1
bloodspasm 2020-05-12 15:38:58 +08:00 1
`当我需要渲染数据的时候我就直接 foreach,数组的下标似乎对我没有任何影响`
你这个数组在 iOS 是 NSDictionary 是无顺序会发生改变的不是固定如果 { "100":{ "id":100 "title":"xxx" }, "105":{ "id":105 "title":"sss" } } 也有可能会返回 { "105":{ "id":105 "title":"sss" },"100":{ "id":100 "title":"xxx" }, } 如果要渲染成列表就会数据显示随机. [ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ]可以正确的保证数据的每次固定.其实作业解析还是有问题因为 app 是使用模型接受数据会很麻烦,推荐这样比较方便[ { "id":100 "title":"xxx" "key":1}, { "id":105 "title":"sss" key":2} ]. |
2
sayitagain OP @bloodspasm
假设数据按要求返回了 [ { "id":100 "title":"xxx" "key":1}, { "id":105 "title":"sss" key":2} ]. 在要求显示 id=100 的数据 title 时,iOS 是怎么处理的? |
3
bloodspasm 2020-05-12 17:17:39 +08:00
@sayitagain { "id":100 "title":"xxx" "key":1} 看成是一个 model,如果 model.id == 100 取 model.title 就行了.如果是是要在大量数据中锁定 id=100 的话,推荐就要做数据预处理,处理成[ "0":model0, "1":model1 ]你同事这种风格用 dictionary[100]去访问.
实际情况列表比较多是[ model0, model1 ] 这种情况,相对较少的会 dictionary[key]这种方式在列表取值.因为用户点击的时候是知道点击数组的第几条的 数组取对应项就行,不用 key 去取值. |
4
local 2020-05-12 17:39:11 +08:00
[{"100":{ "id":100, "title":"xxx" }}, {"105":{ "id":105 ,"title":"sss" } }]
|
6
local 2020-05-12 17:42:38 +08:00
其实外层的 100,105 用处不大。直接返回这种格式的更好
|
7
local 2020-05-12 17:42:46 +08:00 4
[{ "id":100, "title":"xxx"}, { "id":105 ,"title":"sss" }
|
8
loshine1992 2020-05-12 17:45:04 +08:00
你这个其实还好,问题是我合作的 PHP,同一个 API,一下子返回对象,一下子又返回数组,你叫我怎么办,我也很无奈啊。
|
9
0DBBFF 2020-05-12 17:45:22 +08:00
],同意 7L 这种形式,但少了半拉括号
|
10
asAnotherJack 2020-05-12 17:46:17 +08:00
@local #4 这种不行吧,通常 key 应该固定,只改变 value,用 100,105 这种做 key,解析的时候只能解析成 map 了,客户端可能会发飙的
|
11
sayitagain OP @local @bloodspasm 嗯,同事也跟我这么说,对他们基本没什么用还徒增烦恼.按对象数组 php 里的处理方式太方便了,但他们没跟我解释清楚他们的处理方式,我所以有点困惑.
|
12
0DBBFF 2020-05-12 17:48:30 +08:00
@sayitagain 原因很简单,key 是固定的好取值。
|
13
sayitagain OP @asAnotherJack 确实发飙了哈哈,之前我这块代码一直对接的是前端和内部通信,没有什么异议.最近需要开放给 app 才提出了问题,目前通过请求来源对数据做了转换了
|
14
ysc3839 2020-05-12 17:49:49 +08:00 via Android
@bloodspasm 但是 Objective-C 没有提供有序 map 吗?印象中 C++ 和 Java 都有提供吧?用有序 map 就能解决这个问题了。
|
15
kera0a 2020-05-12 17:50:25 +08:00 via iPhone 1
上一个 phper 问这个问题时,被骂了 200 多楼。
|
16
sayitagain OP @ysc3839 app 给我的反馈是能处理,但是麻烦,最好后端直接给出标准格式数据.
|
17
sayitagain OP @kera0a 像用 100,105 这种无序 key 数组,在 php 里实在是太好用了,app 不给我解释我确实很难理解为啥
|
18
kera0a 2020-05-12 17:55:12 +08:00 via iPhone
|
19
HangoX 2020-05-12 17:55:48 +08:00
不难处理,但是你这个是 map,map 迭代没有数组快,js 那些是没有问题,因为本来就不区分,但是强类型语言这个区分得很开。而且 map 如果你是用 hashmap 是不保数序的,你每次还迭代还需要弄个 forint 。那么多蛋疼的事情,我又不需要 1 这个 key,我为何不直接用数组。
|
20
sayitagain OP @kera0a 回复果然很惨烈,我倒不是要说个谁对谁错谁好谁坏,我这边一般是前端 /app 要什么样的给什么...刚好就这个接口是无序 key 返回的,就讨论了下,两 app 开发没跟我解释清楚缘由,我就来好奇问下.
|
21
nicevar 2020-05-12 18:11:32 +08:00
这个问题自己既做客户端又做服务端最清楚了, 客户端最不想看到胡里花哨的数据, 本来一句代码解析的东西, 非要搞出一坨代码来处理, 浪费精力, 而且容易出现隐患, 毕竟客户端版本发出去了再发生变动很难处理, 只能靠强制用户升级之类的操作.
|
22
slyang5 2020-05-12 18:20:47 +08:00
@sayitagain 说实话你返回这种 ,我估计开骂了
|
23
sayitagain OP @slyang5 原始接口并非是给 app 用的,最近 app 也需要就直接给出来了,压根没考虑到这边的这个数据格式
|
24
CommandZi 2020-05-12 18:25:05 +08:00
按字典放回,那么这一组数据在后端固有的顺序去到前端后不就丢失了么
|
25
xrr2016 2020-05-12 18:31:40 +08:00
[ { "id":100 "title":"xxx" "key":1}, { "id":105 "title":"sss" key":2} ] 肯定是这种形式更方便前端 /移动端处理
|
27
newtype0092 2020-05-12 18:52:48 +08:00
没有难不难的,简单来说就是不标准,数组适应性更广,如果不是有特殊的优化需求的话就不要搞特殊。
|
28
zsdroid 2020-05-12 18:59:44 +08:00
问题产生的原因是,php 是弱语言(万物皆数组),java,oc 是强语言(万物皆对象)
|
29
zsdroid 2020-05-12 19:04:40 +08:00
有种情况,phper 经常被骂,有数据时返回[],没数据时返回{}
|
30
charlieputon 2020-05-12 19:07:39 +08:00 via Android
@sayitagain 这个还需要跟你解释,你作为后端难道不是应该你自己去了解吗?基本的 json 格式都不知道,做个鸡儿的后端。这种辣鸡贴子都快月经了
|
31
HongJay 2020-05-12 19:14:01 +08:00
php ?
|
32
deyu 2020-05-12 19:16:47 +08:00
每一行都有自已的难处 相互理解咯
|
33
CodeCodeStudy 2020-05-12 19:31:13 +08:00
@zsdroid 可以用 ArrayObject 解决
```php $data = []; if (!$data) { $data = new \ArrayObject(); } echo json_encode($data); ``` |
34
yuzo555 2020-05-12 19:32:36 +08:00
按语义来说一般是要返回数组,而不是对象的。
PHPH |
35
yuzo555 2020-05-12 19:34:10 +08:00
PHP 如果能提供一种访问数组元素的方式,类似 CSS Selector,比如
$a = [ { "id":100 "title":"xxx" "key":1}, { "id":105 "title":"sss" key":2} ]; $a[id=100] 就能拿到 { "id":100 "title":"xxx" "key":1} 那就刺激了 |
36
MrStark 2020-05-12 20:10:20 +08:00 1
两个原因:
1 、Android 我不清楚,但 iOS 端,key-value pair 的集合是无序的,只有数组才是有序的,如果开发过程中没问题,但上线后顺序出问题了,这个锅谁来背? 2 、客户端完全没必要解析外面 "100"、"105" 这一层,客户端需要把 json 转成模型对象,干嘛费功夫解析一遍外边这层无用的数据呢,外边这一层对于客户端来说完全没有意义。 |
37
youxiachai 2020-05-12 20:19:46 +08:00 1
你这叫 map..不叫带下标数组....
|
38
bbappa 2020-05-12 20:30:14 +08:00
7 楼是对的
|
39
yikuo 2020-05-12 20:37:34 +08:00 via Android
虽然 php 里面的数组是 array 和 map 一体,但你这样用已经不算通常意义上的数组了
|
40
dilu 2020-05-12 20:38:05 +08:00 via Android 1
@loshine1992 其实呢 phper 也挺冤枉的,因为在 php 里面对象跟数组都是数组,如果原本是对象的,对象因为某些原因给了空就会变成数组的 强类型语言对接弱类型语言有很多坑要踩。
|
41
ben1024 2020-05-12 20:46:54 +08:00
数据规范是一个问题,客户端处理能力又是另一个问题
|
42
lagoon 2020-05-12 20:58:58 +08:00 2
不抬杠,冷静探讨。
楼主自己也说,“对象数组”。 也就是说,楼主自己也认为,实际上是要返回“数组”这种东西的。 那么查一查,json 规范,数组是怎么定义的就一目了然。 按照 json 的规范,数组由“[]”包裹。 当然,楼主说这种能不能解析,肯定是有办法解析的。但绕开 json 规范的思路,实现一种自己思路的对象数组,是不是不太好呢? 楼上好几位要加"[]",也是这个缘故。加上了,才是 json 规范思路里的数组,别人也更好的按规范解析了处理。 |
43
gz911122 2020-05-12 22:02:36 +08:00 1
一看后端老哥就是 php 的
|
44
to2false 2020-05-12 22:11:52 +08:00
[ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ]
这种才是对象数组,php 封装一个 json_encode 方法是让你方便不是让你随便 |
45
luozic 2020-05-12 22:20:45 +08:00 via iPhone
不要随便,id 当 key 这种不符合 json 设计规范。
|
46
devjia 2020-05-12 22:30:20 +08:00
你这么搞, 客户端同学没打你就不错了,哈哈哈哈
|
47
mxalbert1996 2020-05-12 23:28:57 +08:00 via Android
我就不懂了,如果你只是为了在 PHP 里方便,那你里面又放一边 id 的意义何在?
|
48
Takuron 2020-05-12 23:30:02 +08:00 via Android
大学生做 Android 的表示这种数据不难处理,类里面单独写个方法遍历字典就好了,少量数据应该也不会明显瓶颈。
但是我要是用 GSON 的项目后端给我这种接口,打他的话带我一个,好好的数组规范用轮子完美无缝衔接的事情。 |
49
nieyujiang 2020-05-12 23:35:11 +08:00
换我估计要扔屏幕.
|
50
weixiangzhe 2020-05-12 23:53:23 +08:00 via Android
js 里也是无序啊,不建议用 object
|
51
tanranran 2020-05-12 23:55:03 +08:00
7 楼最友好,没有之一
|
52
souths 2020-05-13 00:24:53 +08:00
key 别用变量
|
53
souths 2020-05-13 00:35:14 +08:00
{"id":1 "key":"avatar01" "size":"1024" "url":"https://w.v.com/image/1"}
[{"id":1 "key":"avatar01" "size":"1024" "url":"https://w.v.com/image/1"},{"id":1 "key":"avatar01" "size":"1024" "url":"https://w.v.com/image/1"}] Android 这两种种 Json 对应的对象就是: public class FileDTO implements Parcelable { private Long id; /** * 文件名 */ private String key; /** * 大小 */ private String size; /** * 文件地址 */ private String url; } 复制 json 用插件自动生成类的代码,然后用 Gson 自动把接口返回的 Json 变成对象, 用的时候从对象里取值,省时省力 |
54
xFrye 2020-05-13 01:19:40 +08:00
既然是 array,为什么不用 JSONArray 返回?数组下标+JSONObject 来表示一个有序列表的做法我看不懂
|
55
q409195961 2020-05-13 02:11:03 +08:00 1
作为一个好的后端
就应该征求前端的意见,尽量给出前端想要的数据结构 同认可 7L 那种方式 |
56
slyang5 2020-05-13 07:56:30 +08:00
@sayitagain 貌似 PHPer 都不太喜欢 面向对象。 我之前也遇到过这种。
|
57
passerbytiny 2020-05-13 09:22:22 +08:00 via Android 1
我看了回复,再回头看描述,才发现楼主是
{"100":{ "id":100 "title":"xxx" }, "105":{ "id":105 "title":"sss" } } ios 要 [ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ] 。 而不是楼主要 [ { "id":100 "title":"xxx" }, { "id":105 "title":"sss" } ] 而 ios 要 [ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ] 。 那么我的结论如下。 主要的锅是楼主的,不理解强类型语言中 MAP 和 ARRAY 的区别,以及 JSON 中 OBJECT 和 ARRAY 的区别。PHP 中对象 /MAP 跟数组一样,转成 JSON 字符串后也一样,或者楼主所在的 javascript 反解析 JSON 后也一样,楼主就想当然的认为其他语言中也是一样,但那是不一样的。 次要的锅是 ios 的,楼主列的 ios 数据 [ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ] 是不对的,那不是 json,应该是 {"0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" }} 。也就 ios 会这么要,android 会要这样: [ { "id":100 "title":"xxx" }, { "id":105 "title":"sss" } ] 。如果是 android 来要,稍微点一下楼主就会知道 MAP/OBJECT 跟 ARRAY 的区别。 |
59
passerbytiny 2020-05-13 09:31:33 +08:00 via Android
再想想,ios 的那个锅,也得不负责任的 PHP 来背。PHP 没有纯正数组,若 PHP 的 json 解析框架未做负责人的处理,数组转换成 json 后就是 {"0":{ "id":100 "title":"xxx" }, "1":{"id":105 "title":"sss" } } 这种怪异格式。ios 能提出这样的格式要求,八成是因为以前对接 PHP 时见过这种格式。
|
60
yikuo 2020-05-13 09:57:58 +08:00 via Android
@passerbytiny 这锅 php 不背吧,如果是正规用法,php 中纯数组转换成 json 后也是标准 json 形式的[xxx,xxxx],只能说明楼主在混用普通数组和关联数组。
|
61
sayitagain OP @zsdroid 哈哈对,刚入行的时候一直觉得{}/[]是同一个东西...或者说根本没在意这两,现在空值就要下意识的 (object) array()一下
|
62
sayitagain OP @charlieputon 肯定是要什么给什么,我只是问下原因,学习下,不是要分个对错,大佬不必上来就问候.
|
63
guolaopi 2020-05-13 10:16:19 +08:00
卧槽,数组不都是 [{a},{b},{c}...] 这种的吗,
怎么看楼上好多都是 [ a:{a}, b:{b}, c:{c}...] 这种写法,这不是对象吗,为毛要用方括号。。。 令外,这玩意儿可以转成 Dictionary 吧 |
64
Jabin 2020-05-13 10:18:33 +08:00
都能处理啊, 用哪种方式只是看方便谁的问题了(其实也没那么不方便)
|
65
zhjie 2020-05-13 10:22:45 +08:00
不是,培训班这么不负责的吗?
|
66
sayitagain OP @zhjie 说起来有点阴差阳错,我大学主要学的是 c#,J2ME,JSP 这类,毕业设计图书馆找资料,随便看了本 php,当时就卧槽!被 php 弱类型变量吸引了...然后就开始自学...然后毕业设计也用的 php...然后工作也顺理成章是入了 php 这行.
|
67
GM 2020-05-13 10:33:23 +08:00
楼主应该是从 php 等动态语言开始入门的,没接触过静态语言,所以才以为 PHP 的“关联数组”就是“数组”。
事实上,PHP 的关联数组(也就是代码里用的 array() 创建的变量 )是一个混合了数组和 HashTable 的一个数据结构,内部结构是非常复杂的,为的是 web 开发人员用起来方便,但是这个东西是 PHP 特有的,在 Java 、C 、C++、Objective-C 、Swift 等等语言是没有对应的概念的(稀疏数组勉强可以对应,但是稀疏数组依然只有 index,没有 key )。 真正的“数组”没有 key 的,只有数字下标 ( index ),内存里一个元素挨着一个元素,结构紧凑高效,也就是 [{}, {},...] 这种才叫做数组,这就带来一个问题,index 多大,就需要多大的数组,假设用楼主你这种表示法,你传了一个 ["123456": {"id": "123456", "title"}] 的这么个东西,那么如果真要按照数组来解析的话,那么就会创建一个可以容纳为 123456 元素的数组,假设每个元素占 100 个字节,那光这个数组就要占用 123456/1024/1024=11M 的内存,极其费内存,这种东西多了,你设备有多少内存都不够用的。如果服务端用的 ID 还比较大,比如 12345678,那光这个数组就占 1.15 G 内存,嗯....领导会把你按在床上打 PP 的。 |
68
sayitagain OP @GM php 毕业前自学的,学校里学 c#,J2ME,JSP 这类,但我自认为我学的不行.或者说感觉上不适合.
|
69
lxk11153 2020-05-13 10:40:05 +08:00
@charlieputon 基本的 json 格式?楼主说的两种都可以吧,只是用 JsonObject 看是否需要顺序(如 java 的 LinkedHashMap/HashMap)
{ "100":{ "id":100 "title":"xxx" }, "105":{ "id":105 "title":"sss" } } > An object is an unordered set of name/value pairs. An object begins with {left brace and ends with }right brace. Each name is followed by :colon and the name/value pairs are separated by ,comma. [ { "id":100 "title":"xxx" }, { "id":105 "title":"sss" } ] > An array is an ordered collection of values. An array begins with [left bracket and ends with ]right bracket. Values are separated by ,comma. |
70
Leonard 2020-05-13 10:48:49 +08:00
key 不要变,数组就写成数组[ ]形式;同一 key 下的 value 类型不要随便变,别一会是字符串一会是对象
|
71
jeremaihloo 2020-05-13 10:50:27 +08:00
觉得 67 楼说的很棒
|
72
ccppgo 2020-05-13 10:52:34 +08:00
{"100":{"id":100,"title":"xxx"},"105":{"id":105,"title":"sss"}}
array_values() 处理一下重建一下数组索引就好了 |
73
Leonard 2020-05-13 10:52:39 +08:00
你举的例子 [ "0":{ "id":100 "title":"xxx" }, "1":{ "id":105 "title":"sss" } ] 其实都没必要
直接 [ { "id":100 "title":"xxx" }, { "id":105 "title":"sss" } ]最好 |
74
xuanbg 2020-05-13 10:58:10 +08:00
{ "100":{ "id":100 "title":"xxx" }, "105":{ "id":105 "title":"sss" } }这种大多数情况下都不适合用来作为一个集合的数据结构。一般情况下,集合中的元素的 id 是无意义的,也没人关心它的值。这和 k/v 结构中的 key 不同,key 是约定的,是有意义的。
如果前端需要知道 100 这个 key 对应的 value,那么楼主的数据结构是合适的,如果前端只是列表显示,[{ "id":100 "title":"xxx" },{ "id":105 "title":"sss" }]这种结构才是合适的。 |
75
areless 2020-05-13 11:09:53 +08:00 via Android
前端处理上有很大不同,必须[,,,,]
|
76
ww940521 2020-05-13 12:59:26 +08:00
就算你返回一个字符串我也能把它解析出来,然后呢?
该挨揍还是得挨揍 |
78
jowan 2020-05-13 16:08:43 +08:00
在认真看完楼主的问题后,我已经猜到回复了哈哈
|
79
hbolive 2020-05-13 18:03:45 +08:00
一句话:PHP 让你方便(不得不说,直接取下标,有时候是真方便),可不是让你随便。。
PHP:我就不该让你们方便,搞得最后都得我来背锅。。 |