Mastering JsonPath Validation: A Groovy-Powered Framework for Async Socket Testing
This article walks through the design and implementation of a custom JsonPath validation library using Groovy operator overloading, detailing the core enums, verification bean, arithmetic handling, and practical demo code, while providing repository links for Gitee and GitHub.
Overview
Utility library combines JsonPath parsing with Groovy operator overloading to enable flexible validation of JSON responses, especially for asynchronous socket interfaces.
Supported Operations
Comparison operators: > (greater), < (less), = (equal), ~ (regex).
Arithmetic operators applied before comparison: + (add), - (subtract), * (multiply), / (divide).
JsonVerify Implementation
/**
* Determine if the string matches the expectation
*/
public boolean fit(String str) {
logger.info("verify对象: {},匹配的字符串: {}", extra, str);
OPS o = OPS.getInstance(str.charAt(0));
def res = str.substring(1);
switch (o) {
case OPS.GREATER:
return this > res;
case OPS.LESS:
return this < res;
case OPS.EQUAL:
return this == res;
case OPS.REGEX:
return this ==~ res;
default:
ParamException.fail("参数错误!");
}
}
/**
* Determine if the result matches the expectation after an arithmetic operation
*/
public boolean fitFun(String str) {
def split = str.split(REG_PART, 2);
def handle = split[0];
def ops = split[1];
HPS h = HPS.getInstance(handle.charAt(0));
def hr = handle.substring(1);
switch (h) {
case HPS.PLUS:
def n = getInstance((this + hr) as String);
return n.fit(ops);
case HPS.MINUS:
def n = getInstance((this - hr) as String);
return n.fit(ops);
case HPS.MUL:
def n = getInstance((this * hr) as String);
return n.fit(ops);
case HPS.DIV:
def n = getInstance((this / hr) as String);
return n.fit(ops);
default:
ParamException.fail("参数错误!");
}
}
static enum OPS {
GREATER, LESS, EQUAL, REGEX;
static OPS getInstance(char c) {
switch (c) {
case '>': return GREATER;
case '<': return LESS;
case '=': return EQUAL;
case '~': return REGEX;
default: ParamException.fail("判断操作符参数错误!");
}
}
}
static enum HPS {
PLUS, MINUS, MUL, DIV;
static HPS getInstance(char c) {
switch (c) {
case '+': return PLUS;
case '-': return MINUS;
case '*': return MUL;
case '/': return DIV;
default: ParamException.fail("运算操作符参数错误!");
}
}
}VerifyBean Verification Object
package com.fun.base.bean;
import com.alibaba.fastjson.JSON;
import com.fun.base.exception.ParamException;
import com.fun.config.VerifyType;
import com.fun.utils.JsonUtil;
import com.fun.utils.Regex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.fun.config.Constant.REG_PART;
class VerifyBean extends AbstractBean implements Serializable, Cloneable {
private static Logger logger = LoggerFactory.getLogger(VerifyBean.class);
private static final long serialVersionUID = -1595942567071153982L;
VerifyType type;
String verify; // verification expression
String value; // content to verify
String des; // description
boolean isVerify;
boolean result;
VerifyBean(String verify, String value, String des) {
this.value = value;
this.des = des;
String[] split = verify.split(REG_PART, 2);
this.verify = split[1];
this.type = VerifyType.getRequestType(split[0]);
}
boolean verify() {
isVerify = true;
try {
switch (type) {
case CONTAIN:
result = value.contains(verify);
break;
case REGEX:
result = Regex.isRegex(value, verify);
break;
case JSONPATH:
String[] sp = verify.split(REG_PART, 2);
String path = sp[0];
String v = sp[1];
JsonUtil instance = JsonUtil.getInstance(JSON.parseObject(value));
result = instance.getVerify(path).fit(v);
break;
case HANDLE:
String[] hp = verify.split(REG_PART, 2);
String hPath = hp[0];
String hExp = hp[1];
JsonUtil hInst = JsonUtil.getInstance(JSON.parseObject(value));
result = hInst.getVerify(hPath).fitFun(hExp);
break;
default:
ParamException.fail("验证类型参数错误!");
}
} catch (Exception e) {
logger.warn("验证出现问题!", e);
result = false;
} finally {
logger.info("verify对象 {} ,验证结果: {}", verify, result);
}
return result;
}
@Override
public VerifyBean clone() throws CloneNotSupportedException {
return new VerifyBean(this.verify, this.value, this.des);
}
}Demo Usage
public static void main(String[] args) {
String json = "{\"msg\":\"\",\"code\":1,\"data\":{\"role\":\"T\",\"s_sid\":123,\"deviceVersion\":\"1.0\",\"userId\":61951375269,\"token\":\"c5d28b3e919d45e0a06af2e4d346698a\"},\"cmd\":\"registerResponse\"}";
VerifyBean bean1 = new VerifyBean("contain|61951375269", json, "Demo");
VerifyBean bean2 = new VerifyBean("regex|.*data.*", json, "Demo");
VerifyBean bean3 = new VerifyBean("jsonpath|$.data.s_sid|=123", json, "Demo");
VerifyBean bean4 = new VerifyBean("jsonpath|$.data.s_sid|>100", json, "Demo");
VerifyBean bean5 = new VerifyBean("jsonpath|$.cmd|~.*Response.*", json, "Demo");
VerifyBean bean6 = new VerifyBean("handle|$.code|*200|=200.0", json, "Demo");
System.out.println(bean1.verify());
System.out.println(bean2.verify());
System.out.println(bean3.verify());
System.out.println(bean4.verify());
System.out.println(bean5.verify());
System.out.println(bean6.verify());
}Sample Console Output
true
true
true
true
true
trueRepository Links
Gitee: https://gitee.com/fanapi/tester
GitHub: https://github.com/JunManYuanLong/FunTester
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
