alibaba fastjson躺坑记录

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

最近对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 postParam = JSONObject.parseObject(jsonStr, new TypeReference>(){}, Feature.OrderedField);(注意下支持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>(){});
        postParam.put("key3", Arrays.asList("value31", "value32"));
        StringBuilder stringBuilder = new StringBuilder();
        postParam.forEach((k, v) -> stringBuilder.append(v));
        postParam.put("sign", "mySign");
        System.out.println("拼接的字符串为:" + stringBuilder.toString());
        System.out.println("返回处理后的JSON:" + JSON.toJSONString(postParam));
		
输出结果:
拼接的字符串为:["value11","value12"]value2[value31, value32]
返回处理后的JSON:{"key1":["value11","value12"],"key2":"value2","key3":["value31","value32"],"sign":"mySign"}

从上面可以看到,拼接的字符串有错误,缺少了引号",正确的应该是["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>(){});
        postParam.put("key3", Arrays.asList("value31", "value32"));
        
		String json = JSON.toJSONString(postParam);
        postParam = JSON.parseObject(json, new TypeReference>(){});
        
		StringBuilder stringBuilder = new StringBuilder();
        postParam.forEach((k, v) -> stringBuilder.append(v));
        postParam.put("sign", "sign value");
        System.out.println("拼接的字符串为:" + stringBuilder.toString());
        System.out.println("返回处理后的JSON:" + JSON.toJSONString(postParam));

总结

当遇到一些基础库、API返回的结果与预期不符合时,可以的一个猜想是API的默认处理方法与预期不一致,此时应该查看库的java doc或API实现,看是否有相关说明或通过参数控制来达到预期返回。或者借助Google。

转载于:https://my.oschina.net/hebaodan/blog/1554569

你可能感兴趣的:(alibaba fastjson躺坑记录)