따옴표 가 없 는 JSON 문자열 을 자바 가 수 동 으로 해석 하 는 작업
프로젝트 에서 따옴표 가 없 는 JSON 형식의 문자열 을 만 났 습 니 다.
{Name:Heal,Age:20,Tag:[Coding,Reading]}
JSON 대상 으로 해석 한 다음 Elasticsearch 에 삽입 하여 Object 형식의 대상 으로 저장 해 야 합 니 다.
알 리 의 FastJSon,Google 의 Gson 을 비교 해 보 니 원 하 는 기능 을 찾 지 못 했 습 니 다.😛), 그래서 스스로 도구 류 를 써 서 이 수 요 를 실현 했다.
따옴표 가 있 는 표준 JSON 문자열 이 라면 상기 2 가지 도 구 를 통 해 직접 분석 할 수 있 으 며 사용 방법 은 참고 할 수 있 습 니 다.
자바-JSON 문자열 을 포맷 하 는 두 가지 방식
2 분석 코드
2.1 사고의 실현
코드 의 주요 사고방식 은 주석 에 모두 설명 되 어 있 는데 주요 사고방식 은 다음 과 같다.
(1)Stack 통계 문자열 의 앞 뒤[],{}기호―[]대표 List,{}대표 Map;
(2)해 석 된 문자열 을 String\#subString()방법 으로 줄 이기;
(3)내부 의 List,Map 대상 을 재 귀적 으로 분석 합 니 다.
(4)처리 하기 편리 하도록 최소 key-value 는 모두 String 형식 으로 해석 합 니 다.
주의해 야 할 것 은 해석 할 문자열 내부 에 무의미 한{,},[,]기호 가 존재 하지 않 으 면 해석 에 이상 이 생 길 수 있 습 니 다.
-좋 은 호환성 방법 은 잠시 생각 하지 못 했 습 니 다.생각 있 는 동학 은 직접 메 시 지 를 남 겨 주세요.**
2.2 상세 코드
package com.healchow.util;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* Java JSON
*
* @author Heal Chow
* @date 2019/08/13 11:36
*/
public class ParseJsonStrUtils {
public static void main(String[] args) {
// , key-value , fastJson、Gson
// : String {、}、[、] -
/*String sourceStr = "{\"_index\":\"book_shop\"," +
"\"_id\":\"1\"," +
"\"_source\":{" +
"\"name\":\"Thinking in Java [4th Edition]\"," +
"\"author\":\"[US] Bruce Eckel\"," +
"\"price\":109.0,\"date\":\"2007-06-01 00:00:00\"," +
"\"tags\":[\"Java\",[\"Programming\"]" +
"}}";*/
// , []、{}
String sourceStr = "[[[{" +
"{" +
"Type:1," +
"StoragePath:[{Name:/image/2019-08-01/15.jpeg,DeviceID:4401120000130},{ShotTime:2019-08-01 14:44:24}]," +
"Width:140" +
"}," +
"{" +
"Type:2,StoragePath:9090/pic/2019_08_01/src.jpeg," +
"Inner:{DeviceID:44011200}," +
"Test:[{ShotTime:2019-08-01 14:50:14}]," +
"Width:5600}" +
"}}]]]";
List<Map<String, Object>> jsonArray;
Map<String, Object> jsonMap;
Object obj = null;
try {
obj = parseJson(sourceStr);
} catch (Exception e) {
System.out.println(" : " + e.getMessage());
e.printStackTrace();
}
if (obj instanceof List) {
jsonArray = (List<Map<String, Object>>) obj;
System.out.println(" List : " + jsonArray);
} else if (obj instanceof Map) {
jsonMap = (Map<String, Object>) obj;
System.out.println(" Map : " + jsonMap);
} else {
System.out.println(" JSON Array, JSON Object!
: " + sourceStr);
}
}
/**
* Json , List Map
* : (1) key value ",", key ":" ―― "," ":"
* (2) JSON , ,
* "{a:b},{x:y}" ―― "[{a:b},{x:y}]"
* @param sourceStr "[]" "{}"
* @return JsonObject
*/
public static Object parseJson(String sourceStr) throws InvalidParameterException {
if (sourceStr == null || "".equals(sourceStr)) {
return sourceStr;
}
// 、 "[]" "{}"
String parsedStr = simplifyStr(sourceStr, "[", "]");
parsedStr = simplifyStr(parsedStr, "{", "}");
// "[]" "{}"
Stack<String> leftSymbolStack = new Stack<>();
Stack<String> rightSymbolStack = new Stack<>();
if ((parsedStr.startsWith("[") && parsedStr.endsWith("]")) || (parsedStr.startsWith("{") && parsedStr.endsWith("}"))) {
leftSymbolStack.push(parsedStr.substring(0, 1));
rightSymbolStack.push(parsedStr.substring(parsedStr.length() - 1));
parsedStr = parsedStr.substring(1, parsedStr.length() - 1);
// parsedStr "{{}}"
parsedStr = simplifyStr(parsedStr, "{", "}");
} else {
throw new InvalidParameterException(" '[]' '{}', !
: " + sourceStr);
}
// , jsonArray String, Map<String, Object>
List<Object> jsonArray = new ArrayList<>();
Map<String, Object> jsonMap = new HashMap<>(16);
// 、
innerParseByLoop(parsedStr, leftSymbolStack, rightSymbolStack, jsonArray, jsonMap);
// jsonArray
if (jsonArray.size() > 0) {
return jsonArray;
} else {
return jsonMap;
}
}
/**
* List、Map
*/
private static void innerParseByLoop(String parsedStr, Stack<String> leftSymbolStack, Stack<String> rightSymbolStack,
List<Object> jsonArray, Map<String, Object> jsonMap) throws InvalidParameterException {
if (parsedStr == null || parsedStr.equals("")) {
return;
}
// ","
String[] allKeyValues = parsedStr.split(",");
if (allKeyValues.length > 0) {
// , ":"
out:
for (String keyValue : allKeyValues) {
// keyValue ":", keyValue List<Map> , ":" ―― ":"
int index = keyValue.indexOf(":");
if (index > 0) {
// key "{" "[" , ,
String key = keyValue.substring(0, index);
while (key.startsWith("[") || key.startsWith("{")) {
leftSymbolStack.push(key.substring(0, 1));
//
parsedStr = parsedStr.substring(1);
key = key.substring(1);
}
// value "[" ―― List ――
String value = keyValue.substring(index + 1);
if (value.startsWith("[")) {
int innerIndex = parsedStr.indexOf("]");
List<Object> innerList = (List<Object>) parseJson(parsedStr.substring(key.length() + 1, innerIndex + 1));
jsonMap.put(key, innerList);
// "]", ","
parsedStr = parsedStr.substring(innerIndex + 1);
if (parsedStr.indexOf(",") == 0) {
parsedStr = parsedStr.substring(1);
}
// , "," , "," ,
innerParseByLoop(parsedStr, leftSymbolStack, rightSymbolStack, jsonArray, jsonMap);
break;
}
// value "{" ―― Map ――
else if (value.startsWith("{")) {
int innerIndex = parsedStr.indexOf("}");
Map<String, Object> innerMap = (Map<String, Object>) parseJson(parsedStr.substring(key.length() + 1, innerIndex + 1));
jsonMap.put(key, innerMap);
// "}", ","
parsedStr = parsedStr.substring(innerIndex + 1);
if (parsedStr.indexOf(",") == 0) {
parsedStr = parsedStr.substring(1);
}
// , "," , "," ,
innerParseByLoop(parsedStr, leftSymbolStack, rightSymbolStack, jsonArray, jsonMap);
break;
}
// value "]" "}"
else {
while (value.endsWith("]") || value.endsWith("}")) {
//
String right = value.substring(value.length() - 1);
//
String top = leftSymbolStack.peek();
// , ,
if (("}".equals(right) && "{".equals(top)) || ("]".equals(right) && "[".equals(top))) {
leftSymbolStack.pop();
value = value.substring(0, value.length() - 1);
jsonMap.put(key, value);
// "}", ","
parsedStr = parsedStr.substring(key.length() + 1 + value.length() + 1);
if (parsedStr.indexOf(",") == 0) {
parsedStr = parsedStr.substring(1);
}
// , List ,
jsonArray.add(jsonMap);
jsonMap = new HashMap<>(16);
//
continue out;
}
// ,
else {
rightSymbolStack.push(right);
value = value.substring(0, value.length() - 1);
}
}
jsonMap.put(key, value);
int length = key.length() + value.length() + 2;
if (parsedStr.length() > length) {
parsedStr = parsedStr.substring(length);
} else {
parsedStr = "";
}
}
}
// keyValue ":", keyValue List<String> , List<Map> Map, List
else {
jsonArray.add(keyValue);
}
}
// , ――
while (!leftSymbolStack.empty()) {
if (leftSymbolStack.peek().equals("{") && parsedStr.equals("}")) {
leftSymbolStack.pop();
}
if (!rightSymbolStack.empty()) {
if (leftSymbolStack.peek().equals("{") && rightSymbolStack.peek().equals("}")) {
leftSymbolStack.pop();
rightSymbolStack.pop();
} else if (leftSymbolStack.peek().equals("[") && rightSymbolStack.peek().equals("]")) {
leftSymbolStack.pop();
rightSymbolStack.pop();
} else {
throw new InvalidParameterException(" JSON !
: " + parsedStr);
}
}
}
}
}
/**
* 、 "[]" "{}",
*/
private static String simplifyStr(String sourceStr, String firstSymbol, String lastSymbol) {
while (sourceStr.startsWith(firstSymbol) && sourceStr.endsWith(lastSymbol)) {
String second = sourceStr.substring(1, 2);
// "[" "{", "]" "}" ―― 3, IndexOutOfBoundsException
if (second.equals(firstSymbol)) {
String penultimate = sourceStr.substring(sourceStr.length() - 2, sourceStr.length() - 1);
if (penultimate.equals(lastSymbol)) {
//
sourceStr = sourceStr.substring(1, sourceStr.length() - 1);
} else {
break;
}
} else {
break;
}
}
return sourceStr;
}
}
2.3 테스트 사례(1)따옴표 가 있 는 테스트:
// :
String sourceStr = "{\"_index\":\"book_shop\"," +
"\"_id\":\"1\"," +
"\"_source\":{" +
"\"name\":\"Thinking in Java [4th Edition]\"," +
"\"author\":\"[US] Bruce Eckel\"," +
"\"price\":109.0,\"date\":\"2007-06-01 00:00:00\"," +
"\"tags\":[\"Java\",[\"Programming\"]" +
"}}";
분석 결과:(2)따옴표 가 없 는 테스트:
// :
String sourceStr = "[[[{" +
"{" +
"Type:1," +
"StoragePath:[{Name:/image/2019-08-01/15.jpeg,DeviceID:4401120000130},{ShotTime:2019-08-01 14:44:24}]," +
"Width:140" +
"}," +
"{" +
"Type:2,StoragePath:9090/pic/2019_08_01/src.jpeg," +
"Inner:{DeviceID:44011200}," +
"Test:[{ShotTime:2019-08-01 14:50:14}]," +
"Width:5600}" +
"}}]]]";
분석 결과:추가 지식:키 이름 에 따옴표 가 없 는 JSON 문자열 을 JSON 대상 으로 변환 하 는 방법
4json.org위의 설명 에 따 르 면 JSON 대상 은 대상 구성원 으로 구성 되 고 구성원 은 key-value 키 로 구성 된다.
key 값 은 문자열 입 니 다:
문자열 은 유 니 코드 문자 로 구성 되 어 있 으 며,따옴표 로 둘러싸 고,역 슬 래 쉬 로 의 미 를 바 꿉 니 다.단일 문자 일 수 있 습 니 다.용법 은 C 나 자바 의 문자열 의 용법 과 비슷 하 다.
그러나 실제 애플 리 케 이 션 에 서 는 JSON 의 key 가 작은 따옴표 로 둘러싸 여야 한 다 는 것 을 아 는 프로그래머 가 별로 없다.대부분의 브 라 우 저 에 서 는 작은 따옴표 가 필요 하지 않 기 때문이다.그래서 왜 쓸데없는 짓 을 하면 두 개의 따옴표 를 더 써 야 합 니까?
규범 화 된 예:
{
"keyName" : 34
}
규범 에 맞지 않 는 예:
{
keyName : 34
}
브 라 우 저 에서 규범 에 맞지 않 고 더 블 따옴표 를 사용 하지 않 는 쓰기 가 브 라 우 저 에서 문제 가 되 지 않 지만 다른 곳 에서 문제 가 발생 하지 않 을 수 있다 는 것 은 아 닙 니 다.예 를 들 어 문자열 이 있 습 니 다.
//문자열 형식
'{ keyName : 34 }'
너 는 그것 을 JSON 대상 으로 바 꾸 고 싶다.JSON 문자열 을 JSON 대상 으로 변환 하려 면 JSON.parse()방법 을 사용 해 야 합 니 다.위의 키 이름 에 작은 따옴표 가 없 는 JSON 문자열 에 대해 서 는 JSON.parse()를 사용 하여 해석 할 때 오류 가 발생 하여 해석 할 수 없습니다.이것 은 매우 번 거 로 운 문제 가 되 었 다.그 러 니 가능 한 한 규범 적 인 예방 을 사용 하 는 것 이 좋다.비록 대부분 문제 가 없 지만.
그렇다면 키 이름 에 따옴표 가 없 는 JSON 문자열 에 대해 어떻게 JSON 대상 으로 변환 합 니까?
가장 직접적인 방법 은 키 이름 에 작은 따옴표 를 수 동 으로 붙 이 는 것 이다.
만약 당신 이 수 동 으로 추가 하지 않 는 다 면 함수 전문 검색 을 통 해 더 블 따옴표 를 추가 할 수 있 습 니 다.예 를 들 어 아래 의 이 코드 와 같 습 니 다.
json_string.replace(/(s*?{s*?|s*?,s*?)(['"])?([a-zA-Z0-9]+)(['"])?:/g, '$1"$3":');
eval('var json = new Object(' + json_string + ')');
마지막 으로 가장 간단 한 방법 은 eval()로 직접 실행 하 는 것 입 니 다.
var obj = eval('(' + invalid_json + ')');
그러나 이렇게 실행 할 때 실행 코드 가 무엇 인지 이해 해 야 한다.악성 프로그램 이 들 어 있다 면 이렇게 직접 실행 하면 안전 문 제 를 일 으 킬 수 있 기 때문이다.
이 자바 가 따옴표 가 없 는 JSON 문자열 을 수 동 으로 해석 하 는 작업 은 바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.참고 하 시기 바 랍 니 다.많은 응원 부탁드립니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.