最近几天有点郁闷,不是因为别人,而是觉得自己做开发两年时间了,有些基本的东西还是模模糊糊的,导致工作过程在非常被动,而且效率不太如意,公司最近做一个项目,需要跟其它公司的后台做对接,不得不说,后台不在自己公司,对接起来效率真的低很多!下面说下问题!
一、首先,下面是接口文档
我们看到是post请求,参数会全部转换成json的形式,key为content,而我用的是okhttp这个网络框架,所以就有了下面的代码
public void getBody(String json){
FormBody.Builder bodyF = new FormBody.Builder();
bodyF.add("content",json);
RequestBody body= bodyF.build();
}
注:其实一开始我就错了,上面的content的压根就不是指key,content其实就直接是json串了,自己粗心大意导致了后面的问题出现不过问题既然出现了,那就顺便研究研究吧。
2、到了这里,就风风火火的发起网络请求了,然后也访问接口成功了,只不过问题出现了后台出现的json数据变成了下面这个样子,导致无法解析
content=%7B%22content%22%3A%7B%22DataOfObuVehInfo%22%3A%7B%22obuNo%22%3A%2212365953249256354872%22%2C%22posTSN%
22%3A0%2C%22randomForMAC%22%3A%5B49%2C50%2C51%2C52%2C53%2C54%2C55%2C56%2C57%5D%7D%2C%22channelType%22%3A%22fjetc
%22%2C%22charset%22%3A%2202%22%2C%22deviceID%22%3A%2213828899271%22%2C%22deviceType%22%3A%22phone%22%2C%22
merchantId%22%3A%2290812241%22%2C%22notifyUrl%22%3A%22http%3A%2F%2F
紧接着后台就说是我编码不是UTF-8导致出现乱码,可是我一想不对啊,我的数据没有中文,后来尝试了各种方法也不行,最后尝试了下URLDecoder.decode(str,"UTF-8"),结果还真还原了数据,至此终于明白了,原来数据是被编码了,可是自己明明没有做编码的操作
查看FormBody的add方法终于发现,原来数据add进去后是经过了编码的
public FormBody.Builder add(String name, String value) {
if (name == null) throw new NullPointerException("name == null");
if (value == null) throw new NullPointerException("value == null");
names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, false, false, true, true, charset));
values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, false, false, true, true, charset));
return this;
}
是在coanonicalize方法中做的
3、到了这里,后台的哥们也不错,屁颠屁颠的就把数据给做了解码操作(其实真的是我这边的问题。。。),不过先不管了,一切以实现功能为主,至于怎么实现、想能优化,那都是后续的问题!本来以为这就没事了,谁知道,紧接着后台又说数据解析不通过,前面多了个content=,如下的数据:
content={"a":"xxx","b":"xxx"...}所以解析不了
ok,看了下数据,多出来的部分分明就是传递参数的时候的key,估计服务端是直接去读流了,把body里所有数据都读出来了,而不是使用getParameter的方式去读,没办法,只能换成如下方式去生成body public RequestBody getBody(String json){
RequestBody body= RequestBody.create(MediaType.parse("application/json;charset=utf-8"),json);
return body;
}
果然,换成这种方式之后,数据正常了,可是让我豁然开朗的是,后台的哥们跟我说,我改了之后数据没有被编码了,终于隐隐发觉,数据被自动编码原来是跟application/json这个参数有关系,而这就是http里面请求头中的Content-type了。
二、既然知道了是Content-type导致了刚才的问题,那么就好好看下吧
其实在http协议规范中,post提交的数据是放在entity-body中的,但协议并没有规定数据必须使用什么编码方式,实际上是由开发者去选择的,只不过后台也需要根据前端所选择的编码方式去解析。
1、application/x-www-form-urlencoded;charset=utf-8
查看相关文档发现,这种Content-type类型是以form表单的形式提交数据的是基于uri的percent-encoding编码的,所以body中的数据会以key=values的形式进行序列化,而这个编码的过程中,一些特殊符号会通过URL转码转成如4%D3%3F。。。等形式,这就导致了我们前面出现了json数据被做了这样的处理,因为默认情况下okhttp的Content-type默认就是application/x-www-form-urlencoded,这就不难解析为什么后台以流的形式读取数据的时候拿到的数据多了个content=,并且被编码了。
2、application/json;charset=utf-8
这种Content-type的编码方式现在是非常流行的,如果你在请求的时候使用抓包工具进行抓包,你会发现,请求体里面显示的内容是一个标准的json串,而不会像经过URL转码后的数据那样。
好了,决绝了问题,也学到了些许新东西,希望对大家有些用!!