json 해석 신기 jsonpath 기반 사용 설명

18122 단어 json 해석jsonpath
만약 에 프로젝트 수요 가 일부 복잡 한 json 에서 값 을 추출 하여 계산 하 는 것 이 라면 jsonpath+IK(ik-expression)로 처리 하 는 것 이 매우 편리 합 니 다.jsonpath 는 json 안의 값 을 추출 한 다음 에 IK 자체 함수 로 계산 합 니 다.특별한 계산 이 라면 사용자 정의 IK 방법 으로 해결 하고 설정 화가 편리 합 니 다.
jsonpath 의 사용 방법 을 간단하게 소개 하 겠 습 니 다.주요 테스트 는 모두 JSonPathDemo 류 에 있 습 니 다.
다음은 간단 한 자바 프로젝트 데모 입 니 다.

메모:그 중에서 그의 max,min,avg,stddev 함 수 는 다음 과 같이 만 처리 할 수 있 습 니 다.

//            
context.read("$.avg($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
list 에 들 어 갈 수 없습니다.list 에 들 어 오 면 틀 릴 수 있 습 니 다.(다음 오류 쓰기)

//     
Object maxV = context.read("$.max($.result.records[*].loan_type)");
//      
Object maxV = context.read("$.result.records[*].loan_type.max()");
//  json      :"loan_type":"2",    ,"loan_type":2          
잘못된 보고 정 보 는 모두 같 습 니 다.다음 과 같 습 니 다.
Exception in thread "main" com.jayway.jsonpath.JsonPathException: Aggregation function attempted to calculate value using empty array
JSonPathDemo 는 테스트 데모 입 니 다.

public class JsonPathDemo {
 public static void main(String[] args) {
 String json = FileUtils.readFileByLines("demo.json");
 ReadContext context = JsonPath.parse(json);
 //1     name
 List<String> names = context.read("$.result.records[*].name");
 //["  ","  ","  "]
 System.out.println(names);
 //2         
 List<Map<String, String>> objs = context.read("$.result.records[*]");
 //[{"name":"  ","pid":"500234199212121212","mobile":"18623456789","applied_at":"3","confirmed_at":"5","confirm_type":"overdue","loan_type":"1","test":"mytest","all":"2"},{"name":"  ","pid":"500234199299999999","mobile":"13098765432","applied_at":"1","confirmed_at":"","confirm_type":"overdue","loan_type":"3","all":"3"},{"name":"  ","pid":"50023415464654659","mobile":"1706454894","applied_at":"-1","confirmed_at":"","confirm_type":"overdue","loan_type":"3"}]
 System.out.println(objs);
 //3       name
 String name0 = context.read("$.result.records[0].name");
 //  
 System.out.println(name0);
 //4      0   2     
 List<String> name0and2 = context.read("$.result.records[0,2].name");
 //["  ","  "]
 System.out.println(name0and2);
 //5      0      1         [0:2]     0       2
 List<String> name0to2 = context.read("$.result.records[0:2].name");
 //["  ","  "]
 System.out.println(name0to2);
 //6           
 List<String> lastTwoName = context.read("$.result.records[-2:].name");
 //["  ","  "]
 System.out.println(lastTwoName);
 //7      1              1 
 List<String> nameFromOne = context.read("$.result.records[1:].name");
 //["  ","  "]
 System.out.println(nameFromOne);
 //8      3               3 
 List<String> nameEndTwo = context.read("$.result.records[:3].name");
 //["  ","  ","  "]
 System.out.println(nameEndTwo);
 //9   applied_at    2  
 List<Map<String, String>> records = context.read("$.result.records[?(@.applied_at >= '2')]");
 //[{"name":"  ","pid":"500234199212121212","mobile":"18623456789","applied_at":"3","confirmed_at":"5","confirm_type":"overdue","loan_type":"1","test":"mytest","all":"2"}]
 System.out.println(records);
 //10   name      
 List<Map<String, String>> records0 = context.read("$.result.records[?(@.name == '  ')]");
 //[{"name":"  ","pid":"500234199299999999","mobile":"13098765432","applied_at":"1","confirmed_at":"","confirm_type":"overdue","loan_type":"3"}]
 System.out.println(records0);
 //11    test     
 List<Map<String, String>> records1 = context.read("$.result.records[?(@.test)]");
 //[{"name":"  ","pid":"500234199212121212","mobile":"18623456789","applied_at":"3","confirmed_at":"5","confirm_type":"overdue","loan_type":"1","test":"mytest","all":"2"}]
 System.out.println(records1);
 //12    test     
 List<String> list = context.read("$..all");
 //["1","4","2","3"]
 System.out.println(list);
 //12    json            ok 1   records   applied_at  1   
 List<String> ok = context.read("$.result.records[?(@.applied_at == $['ok'])]");
 //["1","4","2","3"]
 System.out.println(ok);
 //13     
 List<String> regexName = context.read("$.result.records[?(@.pid =~ /.*999/i)]");
 //[{"name":"  ","pid":"500234199299999999","mobile":"13098765432","applied_at":"1","confirmed_at":"","confirm_type":"overdue","loan_type":"3","all":"3"}]
 System.out.println(regexName);
 //14    
 List<String> mobile = context.read("$.result.records[?(@.all == '2' || @.name == '  ' )].mobile");
 //["18623456789","13098765432"]
 System.out.println(mobile);
 //14       
 Integer length01 = context.read("$.result.records.length()");
 //3
 System.out.println(length01);
 //15   list        
 List<Integer> length02 = context.read("$.result.records[?(@.all == '2' || @.name == '  ' )].length()");
 //[9,8]
 System.out.println(length02);
 //16    
 Object maxV = context.read("$.max($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //3.0
 System.out.println(maxV);
 //17    
 Object minV = context.read("$.min($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //1.0
 System.out.println(minV);
 //18    
 double avgV = context.read("$.avg($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //2.3333333333333335
 System.out.println(avgV);
 //19    
 double stddevV = context.read("$.stddev($.result.records[0].loan_type,$.result.records[1].loan_type,$.result.records[2].loan_type)");
 //0.9428090415820636
 System.out.println(stddevV);
 //20         
 String haha = context.read("$.result.haha");
 //    
 //Exception in thread "main" com.jayway.jsonpath.PathNotFoundException: No results for path: $['result']['haha']
 //at com.jayway.jsonpath.internal.path.EvaluationContextImpl.getValue(EvaluationContextImpl.java:133)
 //at com.jayway.jsonpath.JsonPath.read(JsonPath.java:187)
 //at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:102)
 //at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:89)
 //at cn.lijie.jsonpath.JsonPathDemo.main(JsonPathDemo.java:58)
 //at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 //at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 //at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 //at java.lang.reflect.Method.invoke(Method.java:498)
 //at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
 System.out.println(haha);
 }
}
pom 파일 도입:

 <dependency>
  <groupId>com.jayway.jsonpath</groupId>
  <artifactId>json-path</artifactId>
  <version>2.3.0</version>
 </dependency>
그 중에서 demo.json 은 테스트 json 입 니 다.

{
 "action": "/interface.service/xxx/queryBlackUserData",
 "all": "1",
 "result": {
 "count": 2,
 "tenant_count": 2,
 "records": [
 {
 "name": "  ",
 "pid": "500234199212121212",
 "mobile": "18623456789",
 "applied_at": "3",
 "confirmed_at": "5",
 "confirm_type": "overdue",
 "loan_type": 1,
 "test": "mytest",
 "all": "2"
 },
 {
 "name": "  ",
 "pid": "500234199299999999",
 "mobile": "13098765432",
 "applied_at": "1",
 "confirmed_at": "",
 "confirm_type": "overdue",
 "loan_type": 3,
 "all": "3"
 },
 {
 "name": "  ",
 "pid": "50023415464654659",
 "mobile": "1706454894",
 "applied_at": "-1",
 "confirmed_at": "",
 "confirm_type": "overdue",
 "loan_type": 3
 }
 ],
 "all": "4"
 },
 "code": 200,
 "subtime": "1480495123550",
 "status": "success",
 "ok": 3
}
FileUtils 클래스 는 xx.json 파일 을 문자열 로 읽 는 json 입 니 다.

public class FileUtils {
 /**
 *          ,             
 */
 public static String readFileByLines(String fileName) {
 File file = new File(fileName);
 BufferedReader reader = null;
 String str = "";
 try {
  InputStream is = FileUtils.class.getClassLoader().getResourceAsStream(fileName);
  reader = new BufferedReader(new InputStreamReader(is));
  String tempString = null;
  int line = 1;
  //       ,    null     
  while ((tempString = reader.readLine()) != null) {
  //     
  str += tempString;
  }
  reader.close();
 } catch (IOException e) {
  e.printStackTrace();
 } finally {
  if (reader != null) {
  try {
   reader.close();
  } catch (IOException e1) {
  }
  }
 }
 return str;
 }
}
json 인터페이스 테스트 의 이기 jsonpath
REST 인 터 페 이 스 를 테스트 할 때 JSON 을 자주 해석 해 야 합 니 다.그러면 오픈 소스 jsonpath 로 진행 할 수 있 습 니 다.그 중에서 인터넷 에서 관련 설 을 보면 좋 은 사용 장면 은 다음 과 같 습 니 다.
1.인터페이스 연결
관련 매개 변수 라 고도 합 니 다.응용 업무 인터페이스 에서 하나의 업무 기능 을 완성 할 때 가끔 은 하나의 인터페이스 가 업무 의 전체 절차 논 리 를 만족 시 키 지 못 할 수도 있 고 여러 개의 인터페이스 가 결합 하여 사용 해 야 한다.간단 한 사례,예 를 들 어 B 인터페이스의 성공 적 인 호출 은 A 인터페이스 에 의존 하고 A 인터페이스의 응답 데이터(response)에서 필요 한 필드 를 얻어 야 한다.B 인 터 페 이 스 를 호출 할 때B 인터페이스 에 B 인터페이스 요청 매개 변수 로 전달 하고 후속 응답 데 이 터 를 받 습 니 다.
인터페이스 관련 은 보통 정규 표현 식 을 사용 하여 필요 한 데 이 터 를 추출 할 수 있 지만 제 이 슨 의 이러한 간결 하고 뚜렷 한 차원 구조,경량급 데이터 교환 형식 에 대해 정규 표현 식 을 사용 하면 닭 을 잡 는 데 소 칼 을 사용 하 는 느낌 이 들 수 밖 에 없다(네,정규 표현 식 을 잘 쓰 지 못 하기 때문에).우 리 는 더욱 간단 하고 직접적인 제 이 슨 데 이 터 를 추출 하 는 방식 이 필요 합 니 다.
2.데이터 검증
여기 의 데이터 검증 은 응답 결과 에 대한 데이터 검증 을 가리킨다
인터페이스 자동화 테스트 에서 간단 한 응답 결과(json)에 대해 기대 결과 와 직접 비교 하여 완전히 같은 지 판단 하면 된다.
예 를 들 어 json{"status":1,"msg":"로그 인 성공"}
3.형식 이 복잡 하 다
특히 일부 데 이 터 는 불확실 성 이 있 고 실제 상황 에 따라 변화 하 는 응답 결과 가 있 으 며,간단 한 판단 이 완전히 같은 지(단언)는 실패 하 는 경우 가 많다.
예:

json {"status":1,"code":"10001","data":[{"id":1,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"1","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-05-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":2,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"2","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-06-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":3,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"3","unfinishedInterest":"1.0","unfinishedPrincipal":"100.00","repaymentDate":"2018-07-27 12:24:01","actualRepaymentDate":null,"status":"0"}],"msg":"      "}
위의 제 이 슨 구 조 는 많은 정 보 를 포함 하고 있 으 며,완전한 매 칭 은 거의 성공 할 수 없다.예 를 들 어 그 중의 createTime 정 보 는 인터페이스 테스트 용례 를 실행 하 는 시간 에 따라 매번 다르다.또한 이 시간 은 응답 결과 에서 비교적 부차적인 정보 로 인터페이스 자동화 테스트 를 할 때 무시 되 는 것 을 선택 할 수 있다.
4.우 리 는 어떤 간단 한 방법 이 필요 하 다.
제 이 슨 에서 우리 가 진정 으로 주목 하 는 정 보 를 추출 할 수 있다.
status 의 값 을 1 로 제시 하면 data 배열 의 모든 대상 의 investId 는 1 이 고 data 에서 세 번 째 대상 의 unfinished Principal 값 은 100.00 입 니 다.이 세 가지 관건 적 인 정보 검증 이 통과 되면 저 희 는 응답 결과 에 문제 가 없다 고 생각 합 니 다.
JSONPATH 는 XPATH 와 비슷 합 니 다.문법 규칙 을 요약 하면:
JSONpath 문법 요소 와 대응 하 는 XPath 요소 의 대 비 를 설명 하 는 표 가 있 습 니 다.
XPath
JSONPath
Description
/
$
뿌리 원 소 를 나타 낸다
.
@
현재 요소
/
. or []
하위 요소
..
n/a
부모 요소
//
..
역귀 하강,JSONPath 는 E4X 에서 참고 한 것 이다.
*
*
모든 요 소 를 나타 내 는 마스크
@
n/a
속성 접근 문자
[]
[]
하위 요소 연산 자
|
[,]
연결 조작 자 는 XPath 결과 에 다른 노드 집합 을 합 칩 니 다.JSONP 는 name 이나 배열 색인 을 허용 합 니 다.
n/a
[start:end:step]
배열 분할 작업 은 ES4 에서 참고 합 니 다.
[]
?()
필터 표현 식 적용
n/a
()
스 크 립 트 표현 식 은 스 크 립 트 엔진 아래 에 사 용 됩 니 다.
()
n/a
Xpath 그룹
다음은 간단 한 제 이 슨 데이터 구조 가 서점 을 대표 합 니 다.(원본 xml 파일 은)

{ "store": {
 "book": [ 
 { "category": "reference",
 "author": "Nigel Rees",
 "title": "Sayings of the Century",
 "price": 8.95
 },
 { "category": "fiction",
 "author": "Evelyn Waugh",
 "title": "Sword of Honour",
 "price": 12.99
 },
 { "category": "fiction",
 "author": "Herman Melville",
 "title": "Moby Dick",
 "isbn": "0-553-21311-3",
 "price": 8.99
 },
 { "category": "fiction",
 "author": "J. R. R. Tolkien",
 "title": "The Lord of the Rings",
 "isbn": "0-395-19395-8",
 "price": 22.99
 }
 ],
 "bicycle": {
 "color": "red",
 "price": 19.95
 }
 }
}
XPath
JSONPath
결실
/store/book/author
$.store.book[*].author
모든 책의 저자
//author
$..author
모든 저자
/store/*
$.store.*
store 의 모든 요소.모든 bookst 와 bicycle
/store//price
$.store..price
store 안의 모든 물건 의 price
//book[3]
$..book[2]
세 번 째 책
//book[last()]
$..book[(@.length-1)]
마지막 책
//book[position()<3]
$..book[0,1]
$..book[:2]
앞의 책 두 권.
//book[isbn]
$..book[?(@.isbn)]
isbn 을 포함 하 는 모든 책 을 걸 러 냅 니 다.
//book[price<10]
$..book[?(@.price<10)]
가격 이 10 보다 낮은 책 을 여과 하 다.
//*
$..*
모든 원소.
예 를 들 어 유닛 테스트 MOCK 에서 이렇게 사용 할 수 있 습 니 다.

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class BookControllerTest { 
 @Autowired
 private MockMvc mockMvc; 
 @MockBean
 private BookRepository mockRepository; 
 /*
 {
  "timestamp":"2019-03-05T09:34:13.280+0000",
  "status":400,
  "errors":["Author is not allowed.","Please provide a price","Please provide a author"]
 }
 */
 //article : jsonpath in array
 @Test
 public void save_emptyAuthor_emptyPrice_400() throws Exception {
 
 String bookInJson = "{\"name\":\"ABC\"}"; 
 mockMvc.perform(post("/books")
  .content(bookInJson)
  .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON))
  .andDo(print())
  .andExpect(status().isBadRequest())
  .andExpect(jsonPath("$.timestamp", is(notNullValue())))
  .andExpect(jsonPath("$.status", is(400)))
  .andExpect(jsonPath("$.errors").isArray())
  .andExpect(jsonPath("$.errors", hasSize(3)))
  .andExpect(jsonPath("$.errors", hasItem("Author is not allowed.")))
  .andExpect(jsonPath("$.errors", hasItem("Please provide a author")))
  .andExpect(jsonPath("$.errors", hasItem("Please provide a price")));
 
 verify(mockRepository, times(0)).save(any(Book.class));
 
 }
}
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기