2019独角兽企业重金招聘Python工程师标准>>>
最近对post json参数做签名、验签处理,在用alibaba fastjson处理json时踩坑不少,记录下来供参考。申明下本文基于alibaba fastjson 1.2.9版本
1、json的value为嵌套json时转为Map乱序问题
当把json转换为Map时,由于对key会进行hash,所以最终的Map的键值对与json的键值对顺序可能是不一致的。如{"c":1,"a":2,"b":3} 经过 JSONObject.parseObject(jsonStr, new TypeReference
,结果可能为{"a":2,"b":3,"c":1},如果想保持有序,替换为LinkedHashMap
就行。
但是,如果json中嵌套json的情况,嵌套的json转换后仍然可能与原序不一致,如{"abc":"123","fed":{"c":1, "a":2, "b":3}} 转换后Map输出可能为{abc=123, fed={"a":2,"b":3,"c":1}},如果想保证嵌套的json转换后扔保持原序,可以用Map
(注意下支持Feature.OrderedField的版本)。
2、Map转json后value为null的字段丢失
通常我们会通过JSON.toJSONString(map)
把map转换为json,但默认情况下map中value为null的字段会被过滤调,也就是json中不包含该字段了。如下:
Map postParam = new HashMap<>();
postParam.put("key1", "v1");
postParam.put("key2", null);
Map nestedParam = new HashMap<>();
nestedParam.put("a", null);
nestedParam.put("b", "2");
postParam.put("key3", nestedParam);
System.out.println(JSON.toJSONString(postParam));
//执行的结果是{"key1":"v1","key3":{"b":"2"}}, key2以及key3对应的嵌套json中value为null的key value都被过滤了
解决方案 采用JSON.toJSONString(map, SerializerFeature.WriteNullStringAsEmpty)
,上述举例即可得到{"key1":"v1","key2":null,"key3":{"a":null,"b":"2"}}
3、json根节点下添加array value处理细节不当导致引号"
丢失
场景举例:需要在json根节点下添加一组参数key value(value为string array类型)后把所有value拼接为一个字符串,生成签名(即再添加一组key value形如"sign":"sign value"),再转换为json返回。 假设需要在json串 {"key1":["value11", "value12"],"key2":"value2"}
添加"key3":["value31","value32"]
和sign串"sign":"sign value"
, 且需要把json根节点下的所有value拼接。 代码如下:
String json = "{\"key1\":[\"value11\", \"value12\"],\"key2\":\"value2\"}";
Map postParam = JSONObject.parseObject(json, new TypeReference
从上面可以看到,拼接的字符串有错误,缺少了引号"
,正确的应该是["value11","value12"]value2["value31", "value32"] 原因是往map里put的List中每个元素值就是不带引号"
的 解决方案
可以在put key3后先转换为json,再转为map
String jsonStr = "{\"key1\":[\"value11\", \"value12\"],\"key2\":\"value2\"}";
Map postParam = JSONObject.parseObject(jsonStr, new TypeReference
总结
当遇到一些基础库、API返回的结果与预期不符合时,可以的一个猜想是API的默认处理方法与预期不一致,此时应该查看库的java doc或API实现,看是否有相关说明或通过参数控制来达到预期返回。或者借助Google。