Author:赵志乾
Date:2019-08-29
Declaration:All Right Reserved!!!
踩坑
场景:HttpPost使用StringEntity配置请求体。
做法:使用json-lib包中的JSONObject设置参数,并通过JSONObject的toString方法获取的json串构建StringEntity。发送端实际发送数据和期望发送数据不一致。如下:
// 发送端数据构建
JSONObject jsonBody= new JSONObject();
jsonBody.put("sign", "541df7b19d38b575ec8001bb5e50a5fc");
jsonBody.put("data","{\"name\":\"baixiaoyuan\",\"age\":18,\"score\":100");
StringEntity entity = new StringEntity(jsonBody.toString(), "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
// 发送端要发送的数据
{"data":"{\"name\":\"baixiaoyuan\",\"age\":18,\"score\":100}","sign":"541df7b19d38b575ec8001bb5e50a5fc"}
// 发送端实际发送的数据
{"data":{"name":"baixiaoyuan","age":18,"score":100},"sign":"541df7b19d38b575ec8001bb5e50a5fc"}
解决方案
该问题产生的原因是json-lib包中JSONObject在put操作时,会对其放入的value值多做一层转化操作。源码如下:
public Object put(Object key, Object value) {
if (key == null) {
throw new IllegalArgumentException("key is null.");
} else {
Object previous = this.properties.get(key);
// 看下面element的构建过程
this.element(String.valueOf(key), value);
return previous;
}
}
// element构建过程,调用重载函数
public JSONObject element(String key, Object value) {
return this.element(key, value, new JsonConfig());
}
// element构建过程的重载函数
public JSONObject element(String key, Object value, JsonConfig jsonConfig) {
this.verifyIsNull();
if (key == null) {
throw new JSONException("Null key.");
} else {
if (value != null) {
// 对value做了转换处理
value = this.processValue(key, value, jsonConfig);
this._setInternal(key, value, jsonConfig);
} else {
this.remove(key);
}
return this;
}
}
// value的转换处理过程
private Object processValue(String key, Object value, JsonConfig jsonConfig) {
if (value != null) {
// 查找value的处理器
JsonValueProcessor processor = jsonConfig.findJsonValueProcessor(value.getClass(), key);
if (processor != null) {
// 对value进行转换处理
value = processor.processObjectValue((String)null, value, jsonConfig);
if (!JsonVerifier.isValidJsonValue(value)) {
throw new JSONException("Value is not a valid JSON value. " + value);
}
}
}
return this._processValue(value, jsonConfig);
}
方案:如果不希望JSONObject做隐含转换时,要使用fastjson包的JSONObject。两者对比如下:
// 测试代码
com.alibaba.fastjson.JSONObject jsonBody1 = new com.alibaba.fastjson.JSONObject();
jsonBody1.put("sign", "541df7b19d38b575ec8001bb5e50a5fc");
jsonBody1.put("data","{\"name\":\"baixiaoyuan\",\"age\":18,\"score\":100}");
System.out.println("---fastjson---");
System.out.println(jsonBody1.toString());
net.sf.json.JSONObject jsonBody2 = new net.sf.json.JSONObject();
jsonBody2.put("sign", "541df7b19d38b575ec8001bb5e50a5fc");
jsonBody2.put("data","{\"name\":\"baixiaoyuan\",\"age\":18,\"score\":100}");
System.out.println("---json-lib---");
System.out.println(jsonBody2.toString());
// 输出结果
---fastjson---
{"data":"{\"name\":\"baixiaoyuan\",\"age\":18,\"score\":100}","sign":"541df7b19d38b575ec8001bb5e50a5fc"}
---json-lib---
{"sign":"541df7b19d38b575ec8001bb5e50a5fc","data":{"name":"baixiaoyuan","age":18,"score":100}}
建议:使用新的api时,要多做几次试验,了解其特性,避免理解错误而踩坑