项目地址
https://github.com/json-path/JsonPath
Maven依赖
<!-- jsonpath support -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
测试用例
可用于对json字符串的编辑,修改,删除
public class JsonPathTest {
@Test
public void t1() {
String json = "{\n" +
" \"store\": {\n" +
" \"book\": [\n" +
" {\n" +
" \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.95\n" +
" },\n" +
" {\n" +
" \"category\": \"fiction\",\n" +
" \"author\": \"Evelyn Waugh\",\n" +
" \"title\": \"Sword of Honour\",\n" +
" \"price\": 12.99\n" +
" },\n" +
" {\n" +
" \"category\": \"fiction\",\n" +
" \"author\": \"Herman Melville\",\n" +
" \"title\": \"Moby Dick\",\n" +
" \"isbn\": \"0-553-21311-3\",\n" +
" \"price\": 8.99\n" +
" },\n" +
" {\n" +
" \"category\": \"fiction\",\n" +
" \"author\": \"J. R. R. Tolkien\",\n" +
" \"title\": \"The Lord of the Rings\",\n" +
" \"isbn\": \"0-395-19395-8\",\n" +
" \"price\": 22.99\n" +
" }\n" +
" ],\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95\n" +
" }\n" +
" },\n" +
" \"expensive\": 10\n" +
"}";
String newJson = JsonPath.parse(json).set("$.store.book[0].title", "lucas").jsonString();
System.out.println(newJson);
System.out.println("===");
String newJson1 = JsonPath.parse(newJson).put("$.store.book[0]", "hello", "你好").jsonString();
System.out.println(newJson1);
System.out.println("===");
String newJson2 = JsonPath.parse(newJson1).delete("$.store.book[0].hello").jsonString();
System.out.println(newJson2);
}
}
开源项目的应用
在apache shenyu
项目中ModifyResponsePlugin
有用到JsonPath
/**
* ModifyResponse plugin.
*/
public class ModifyResponsePlugin extends AbstractShenyuPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ModifyResponsePlugin.class);
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {
ShenyuContext shenyuContext = exchange.getAttribute(Constants.CONTEXT);
assert shenyuContext != null;
ModifyResponseRuleHandle ruleHandle = ModifyResponsePluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(rule));
if (Objects.isNull(ruleHandle)) {
return chain.execute(exchange);
}
return chain.execute(exchange.mutate()
.response(new ModifyResponseDecorator(exchange, ruleHandle)).build());
}
static class ModifyResponseDecorator extends ServerHttpResponseDecorator {
private final ServerWebExchange exchange;
private final ModifyResponseRuleHandle ruleHandle;
ModifyResponseDecorator(final ServerWebExchange exchange,
final ModifyResponseRuleHandle ruleHandle) {
super(exchange.getResponse());
this.exchange = exchange;
this.ruleHandle = ruleHandle;
}
@Override
@NonNull
public Mono<Void> writeWith(@NonNull final Publisher<? extends DataBuffer> body) {
ClientResponse clientResponse = this.buildModifiedResponse(body);
Mono<byte[]> modifiedBody = clientResponse.bodyToMono(byte[].class)
.flatMap(originalBody -> Mono.just(modifyBody(originalBody)));
return ResponseUtils.writeWith(clientResponse, this.exchange, modifiedBody, byte[].class);
}
private byte[] modifyBody(final byte[] responseBody) {
try {
String bodyStr = modifyBody(new String(responseBody, StandardCharsets.UTF_8));
LOG.info("the body string {}", bodyStr);
return bodyStr.getBytes(StandardCharsets.UTF_8);
} catch (Exception e) {
LOG.error("modify response error", e);
throw new ShenyuException(String.format("response modify failure. %s", e.getLocalizedMessage()));
}
}
private String modifyBody(final String jsonValue) {
DocumentContext context = JsonPath.parse(jsonValue);
if (CollectionUtils.isNotEmpty(this.ruleHandle.getAddBodyKeys())) {
this.ruleHandle.getAddBodyKeys().forEach(info -> context.put(info.getPath(), info.getKey(), info.getValue()));
}
if (CollectionUtils.isNotEmpty(this.ruleHandle.getReplaceBodyKeys())) {
this.ruleHandle.getReplaceBodyKeys().forEach(info -> context.renameKey(info.getPath(), info.getKey(), info.getValue()));
}
if (CollectionUtils.isNotEmpty(this.ruleHandle.getRemoveBodyKeys())) {
this.ruleHandle.getRemoveBodyKeys().forEach(context::delete);
}
return context.jsonString();
}
}
}