package com.uc.xishuashua.app.tools.json;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import com.uc.xishuashua.app.tools.common.DoubleLinkedList;
/**
* 根据json自动返回相应值的路径
* getSign有个BUG没做,使用时注意
* @author wangle 312300491
*/
public class JsonPathLib {
// Stack为基本计算,遇到{入栈,遇到}出栈,最后栈内剩下的则为路径{{{的形式
Stack<String> signs = new Stack<>();
Stack<String> names = new Stack<>();
public DoubleLinkedList<Integer> arrayStackIndexs = new DoubleLinkedList<>();
static String tag = "", wholeJson = "";
// 1,基本路径组合,map
// 2,参照zjson
// 3,返回所有相同值的json路径
public static void main(String[] args) throws InterruptedException, IOException {
tag = "preload";
FileInputStream input = new FileInputStream(new File(
"D:\\json.txt"));//注意相关路径
int count = 0;
StringBuffer sb = new StringBuffer();
while ((count = input.read()) != -1) {
sb.append((char) count);
}
wholeJson = sb.toString();
List<Integer> indexs = getIndex(tag, sb.toString());
for (Integer integer : indexs) {
JsonPathLib lib = new JsonPathLib();
lib.getSign(integer, sb.toString());
System.out.println(lib.getPath());
}
}
/**
* 获取json中所有想要jsonpath匹配的字段的index位置
*/
public static List<Integer> getIndex(String tag, String json) {
List<Integer> indexs = new ArrayList<>();
int count = 0;
int index = 0;
for (;;) {
index = json.indexOf(tag, count);
if (index == -1)
break;
indexs.add(index);
count = (index += 4);
}
return indexs;
}
/**
* 获取json index位置之前的所有大括号和中括号
* 这里有个逻辑没做,如果双引号之间存在{}[]符号,会导致错误。
* @throws InterruptedException
*/
public void getSign(int index, String json) throws InterruptedException {
boolean isInArray = false;
String tmp = new String(json.substring(0, index));
for (int i = 0; i < tmp.length(); i++) {
char t = tmp.charAt(i);
switch (t) {
case '{':
if(isInArray){//array有两种,一种是[{}]一种是[] 计算方式一致:[开始 ,]结束 增加一项,有{的时候,数组需要重新计算index,
arrayStackIndexs.removeLast();
arrayStackIndexs.add(i);// 由于是从左往右计算路径,所以i为wholejson中的index
}
signs.push("{");
names.push(getKey(json.substring(0, i)));
continue;
case '}':
names.pop();
signs.pop();
continue;
case '[':
isInArray=true;
arrayStackIndexs.add(i);
signs.push("[");
names.push(getKey(json.substring(0, i)));
continue;
case ']':
isInArray=false;
arrayStackIndexs.removeLast();
names.pop();
signs.pop();
continue;
default:
continue;
}
}
}
/**
* 遇到大括号的时候,取大括号外面的key 例如:"3067950993586070768": {取3067950993586070768
* 这里应该有个类可以替换这里的算法,忘了什么类了StringUtils不靠谱,时间复杂度是O(n)
*/
public static String getKey(String str) {
StringBuffer key = new StringBuffer();
boolean begin = false;
for (int i = str.length() - 1; i >= 0; i--) {
char t = str.charAt(i);
if (begin) {
if ('"' == t) {// end
return sort(key.toString());
}
key.append(t);
} else {
if ('"' == t) {// begin
begin = true;
continue;
}
}
}
return "";
}
/**
* 给中括号取一些属性,留给最后计算路径的时候替换掉*用,例如*,替换为 *[?(@.id='')]
*
* @param index为[号位置
* @return map.key:属性的key map.value 属性的value
*/
public static Map<String, String> getValuePairs(int index) {
// value双引号替换成单引号,其他原封不动
Map<String, String> result = new HashMap<>();
StringBuffer sb = new StringBuffer();
boolean begin = true;
boolean keyb = true;
String key = "";
for (int i = index; i < wholeJson.length() - 1&&result.size()<2; i++) {
char t = wholeJson.charAt(i);
if (!begin) {
if (('"' == t&&keyb==true)||','==t) {// end
if (keyb == true) {
key = sb.toString();
sb=new StringBuffer();
keyb=false;
begin=true;
} else {
result.put(key, sb.toString().replace(":", "").replace("\"", "'"));
keyb = true;
begin=true;
key="";
sb=new StringBuffer();
continue;
}
}else{
sb.append(t);
}
} else {
if ('"' == t||':'==t) {// begin
begin = false;
continue;
}
}
char[] signs = { ']', '}' };
int count = Arrays.binarySearch(signs, t);
if (count > 0) {
return result;// 这里已经不满足搜索条件了
}
}
return result;
}
/**
* 生成最后的jsonpath路径,形如$.data.ttt.*[?(@.id=123)].id
*/
public String getPath() {
List<String> list = new LinkedList<>();// List做整体倒序用
while (!signs.empty()) {
String sign = signs.pop();
String name = names.pop();
list.add(sign);
list.add(name);
}
StringBuilder sb = new StringBuilder();
sb.append("$");
for (int i = list.size() - 1; i >= 0; i--) {
sb.append(replaceSign(list.get(i)));
if (list.get(i) == "[") {// 这里因为{[是配套的,少做一次pop操作,在这里补上
i = i - 2;
}
}
sb.append(tag);
return sb.toString();
}
/**
* 最后符号路径换jsonpath路径
*/
public String replaceSign(String sign) {
switch (sign) {
case "{":
return ".";
case "[":
StringBuilder sb = new StringBuilder();
sb.append(".*");
Map<String,String> map = getValuePairs(arrayStackIndexs.removeFirst());
for (String key : map.keySet()) {
String value = map.get(key);
sb.append("[?(@."+key+"="+value+")]");
}
sb.append(".");
return sb.toString();
default:
return sign;
}
}
/**
* 倒序 回溯中产生倒序字符串,需要再进行倒序
*
* @param 123
* @return 321
*/
public static String sort(String str) {
StringBuffer key = new StringBuffer();
for (int i = str.length() - 1; i >= 0; i--) {
char t = str.charAt(i);
key.append(t);
}
return key.toString();
}
}
读json文件自动生成jsonpath
3星 · 超过75%的资源 需积分: 48 188 浏览量
2016-07-22
17:22:20
上传
评论 6
收藏 3KB RAR 举报
kinghappy007
- 粉丝: 1
- 资源: 5
最新资源
- 基于yolov5识别算法实现的DNF自动脚本源码.zip
- 基于Python实现的自动化办公项目.zip
- 基于python实现的基于PyQt5和爬虫的小说阅读系统.zip
- 机械设计整经机上纱自动化sw20非常好的设计图纸100%好用.zip
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈