接口测试 jmeter BeanShell 使用 fastjson 解析数据后导致顺序改变问题

萧帅 · 2021年08月24日 · 最后由 mzy 回复于 2022年04月26日 · 2954 次阅读

元数据 json 字符串如下:
{
"clientId": "89BA44E0B3FD2033623762A4DF0DE182",
"company": "顺丰",
"contactName": "韩德翰",
"contactPhone": "15378028370",
"goodsNumber": "1630655848",
"method": "orders_ship_success",
"shipTime": "2021-08-23 14:42:37",
"mx":[{
"batchNum": "000111",
"goodsItemNumber": "1630655848",
"orderItemNum": "9210823144249361_1",
"productCode": "0000035",
"productNm": "布洛芬混悬液",
"productUnit": "盒",
"quantity": 10},
{
"batchNum": "0007",
"goodsItemNumber": "16306558481",
"orderItemNum": "9210823144249361_2",
"productCode": "0000731",
"productNm": "妇炎洁洗液",
"productUnit": "盒",
"quantity": 10}],
"ncCode": "sap",
"orderNum": "9210823144249361",
"shipType": 1,
"sign": "474464FA525E039E14E565C0AA179335",
"timeStamp": 1629700971,
"version": "1.0"
}

BeanShell 脚本如下:

import org.apache.commons.codec.digest.DigestUtils; 
import java.util.Date;
import java.util.List;
import org.apache.jmeter.config.*; 
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.*;
//import net.sf.json.JSONObject;

Arguments args = sampler.getArguments();   // 截获请求,包含url、headers 和 body 三部分
Argument arg_body = args.getArgument(0);   // 获取请求body
String body = arg_body.getValue();         // 获取body的值保存成字符串
log.info(body);     // 打印下看看,跑压测时勿忘把log注掉
JSONObject jso = JSONObject.parseObject(body); // 把body转成json对象
System.out.println(jso);

打印结果如下:
{clientId=89BA44E0B3FD2033623762A4DF0DE182, company=顺丰, contactName=韩德翰, contactPhone=15378028370, goodsNumber=1630655848, method=orders_ship_success, mx=[{goodsItemNumber=1630655848, productNm=布洛芬混悬液, productCode=0000035, quantity=10,batchNum=000111, orderItemNum=9210823144249361_1, productUnit=盒}, {goodsItemNumber=16306558481, productNm=妇炎洁 洗液, productCode=0000731, quantity=10,batchNum=0007, orderItemNum=9210823144249361_2, productUnit=盒}], ncCode=sap, orderNum=9210823144249361, shipTime=2021-08-23 14:42:37, shipType=1, timeStamp=1629700971, version=1.0}

使用 JSONObject jso = JSONObject.parseObject(body) 转换后,mx 数组结果顺序与原有顺序不一致:

mx=[{goodsItemNumber=1630655848, productNm=布洛芬混悬液, productCode=0000035, quantity=10,batchNum=000111, orderItemNum=9210823144249361_1, productUnit=盒}, {goodsItemNumber=16306558481, productNm=妇炎洁 洗液, productCode=0000731, quantity=10,batchNum=0007, orderItemNum=9210823144249361_2, productUnit=盒}]

通过度娘搜索看到如下解决方案:

Feature.OrderedField--作用解析时增加参数不调整顺序
JSONObject jso = JSONObject.parseObject(body,Feature.OrderedField);

fastjson 版本 1.2.78,但是在 jmeter BeanShell 一直报错:

2021-08-24 15:26:17,003 ERROR o.a.j.u.BeanShellInterpreter: Error invoking bsh method: eval Sourced file: inline evaluation of: import org.apache.commons.codec.digest.DigestUtils; import java.util.Date; impo . . . '' : Typed variable declaration : Class or variable not found: Feature.OrderedField
2021-08-24 15:26:17,003 WARN o.a.j.m.BeanShellPreProcessor: Problem in BeanShell script. org.apache.jorphan.util.JMeterException: Error invoking bsh method: eval Sourced file: inline evaluation of:
import org.apache.commons.codec.digest.DigestUtils; import java.util.Date; impo . . . '' : Typed variable declaration : Class or variable not found: Feature.OrderedField

这个问题困扰了我很久,也在网上找了很多大牛给出的解决方案都不行,可能他们没有遇到我这种问题把,

最终解决方案:

最终结果使用 jmeter 自带 json-lib-2.2.3-jdk15.jar 包 JSONObject.fromObject(jsonStr) 方法,但是这种方法有缺陷,为 null 的话不能使用,

导入 import net.sf.json.JSONObject
使用:JSONObject jso = JSONObject.fromObject(jsonStr);

最终结果:

[{batchNum=000111, goodsItemNumber=1630655848, orderItemNum=9210823144249361_1, productCode=0000035, productNm=布洛芬混 悬液, productUnit=盒, quantity=10}, {batchNum=0007, goodsItemNumber=16306558481, orderItemNum=9210823144249361_2, productCode=0000731, productNm=妇炎洁洗液, productUnit=盒, quantity=10}]

与原有顺序一致

共收到 4 条回复 时间 点赞

欢迎大佬指点,看看有没有最优方案参考,再次感谢!!

1、json 一般对顺序是没有要求的
2、如果有要求,你可以自己封装一个 Jar 工具类。这样就不会报错了

兔子 回复

一般情况下是没有要求,但是对于需要进行 sign 验证,双方接口接收传输有要求

兔子🐰 [该话题已被删除] 中提及了此贴 02月18日 16:23

想请教一下,是否可以通过 addArgument 方法将 json 对象传进 request body 中呢?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册