
一直以来有个疑问,之前公司的 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 `当我需要渲染数据的时候我就直接 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 [{ "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 上一个 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 、Android 我不清楚,但 iOS 端,key-value pair 的集合是无序的,只有数组才是有序的,如果开发过程中没问题,但上线后顺序出问题了,这个锅谁来背? 2 、客户端完全没必要解析外面 "100"、"105" 这一层,客户端需要把 json 转成模型对象,干嘛费功夫解析一遍外边这层无用的数据呢,外边这一层对于客户端来说完全没有意义。 |
37 youxiachai 2020-05-12 20:19:46 +08:00 你这叫 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 @loshine1992 其实呢 phper 也挺冤枉的,因为在 php 里面对象跟数组都是数组,如果原本是对象的,对象因为某些原因给了空就会变成数组的 强类型语言对接弱类型语言有很多坑要踩。 |
41 ben1024 2020-05-12 20:46:54 +08:00 数据规范是一个问题,客户端处理能力又是另一个问题 |
42 lagoon 2020-05-12 20:58:58 +08:00 不抬杠,冷静探讨。 楼主自己也说,“对象数组”。 也就是说,楼主自己也认为,实际上是要返回“数组”这种东西的。 那么查一查,json 规范,数组是怎么定义的就一目了然。 按照 json 的规范,数组由“[]”包裹。 当然,楼主说这种能不能解析,肯定是有办法解析的。但绕开 json 规范的思路,实现一种自己思路的对象数组,是不是不太好呢? 楼上好几位要加"[]",也是这个缘故。加上了,才是 json 规范思路里的数组,别人也更好的按规范解析了处理。 |
43 gz911122 2020-05-12 22:02:36 +08:00 一看后端老哥就是 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 ZeoKarl 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 作为一个好的后端 就应该征求前端的意见,尽量给出前端想要的数据结构 同认可 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 我看了回复,再回头看描述,才发现楼主是 {"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:我就不该让你们方便,搞得最后都得我来背锅。。 |