이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

코딩/Python

파이썬 dictionary를 Json형식으로 저장할 때 Escape Sequence 문제 해결

이쿠우우 2021. 6. 6. 19:25
반응형

 

 

파이썬 dictionary를 Json형식으로 저장할 때 Escape Sequence 문제 해결

 

 

오류 상황

File을 List 자료형으로 Read한 후에

List에 저장되어있는 Data를 Dictionary 자료형의 value로 저장한 뒤

Dictionary 자료형을 json 형식으로 파일 저장하기 위해

import json 또는 pickle을 사용하면 Escape Sequence 문제가 발생함.

 

문제 상황 예제

1. test.log 파일에 아래와 같은 데이터가 있음.

"/bin/grep hfsplus | /bin/awk \'{print} END {if (NR == 0) print \"pass\" ; else print \"fail\"}\'"

 

2. 해당 파일을 읽어서 List에 저장함.

    file = open('./test.log', 'r', encoding='utf-8')

    temp = []

    while True:
        line = file.readline()
        if not line: break
        temp.append(line)
    file.close()

 

3. List의 data를 dictionary의 value로 저장함.

key = test

value = file에서 읽어온 후 list에 저장되어있는 data

    testdictionary = {}
    testdictionary["test"] = temp[0]

4. json 라이브러리를 사용해서 해당 dictionary를 json 형식으로 file write함.

import json
    
    with open('./testJson.log', 'w', encoding='utf-8') as outFile:
        json.dump(testdictionary, outFile, indent="\t")

 

5. 결과 확인

origin의 경우 아래와 같은데

\'{print} END {if (NR == 0) print \"pass\" ; else print \"fail\"}\'

 

import json을 사용해서 json 형식으로 저장할 시

"\\'{print} END {if (NR == 0) print \\\"pass\\\" ; else print \\\"fail\\\"}\\'"

 

이렇게 파이썬에서 dictionary형식 File저장 시 json라이브러리 사용하면

Escape Sequence를 위와같이 한번 더 처리해서 저장하는 현상이 있었음.

파이썬에서 제공하는 pickle, json 모두 동일한 증상을 가지고 있음.

 

 

해결법

 

해당 문제를 해결하기 위해

dictionary type을 json으로 저장 시

Escape Sequence를 그대로 유지하는 함수를 직접 개발함.

코드는 아래와 같음.

 

코드

def debugLogJsonType_EscapeSequenceOrigin(fileName, path, log):

    if not os.path.isdir(path):                                                           
        os.mkdir(path)
    path += "/"

    tabCount = 1
    try:
        with open(path + fileName,'w') as file:
            file.write('{\n')
            count = 1
            checkLast = False
            for key, value in log.items():            
                if len(log) == count :
                    checkLast =  True
                file.write('\t')
                if "<class 'list'>" == str(type(value)) :
                    file.write('"%s": '  % (key) )
                    debugLogJsonType_IfList(file, value, tabCount, checkLast)
                elif "<class 'dict'>" == str(type(value)) :
                    file.write('"%s": ' % (key) )
                    debugLogJsonType_IfDict(file, value, tabCount, checkLast)
                else :
                    if False == checkLast :
                        file.write('"%s": "%s",\n' % (key, value))
                    else :
                        file.write('"%s": "%s"\n' % (key, value))
                count = count + 1
            file.write('}')
        file.close()
    except (Exception) as e:
        print(f"except : {e}")


def debugLogJsonType_IfList(file, log, tabCount, checkLastRoot):

    file.write('[\n')
    tabCount = tabCount + 1   

    checkLast = False

    for number in range(len(log)):
        data = log[number]
        if len(log) -1 == number :
            checkLast =  True
        debugLogJsonType_WriteTab(file, tabCount)

        if "<class 'list'>" == str(type(data)) :            
            debugLogJsonType_IfList(file, data, tabCount, checkLast)
        elif "<class 'dict'>" == str(type(data)) :
            debugLogJsonType_IfDict(file, data, tabCount, checkLast)
        else :
            if False == checkLast :
                file.write('"%s",\n' % (data))
            else :
                file.write('"%s"\n' % (data))

    debugLogJsonType_WriteTab(file, tabCount-1)

    if False == checkLastRoot :
        file.write('],\n')
    else :
        file.write(']\n')

def debugLogJsonType_IfDict(file, log, tabCount, checkLastRoot):

    file.write('{\n')
    tabCount = tabCount + 1   
    count = 1
    checkLast = False

    for key, value in log.items():     
        if len(log) == count :
            checkLast =  True       
        file.write('\t')
        if "<class 'list'>" == str(type(value)) :
            debugLogJsonType_WriteTab(file, tabCount-1)
            file.write('"%s": '  % (key) )
            debugLogJsonType_IfList(file, value, tabCount, checkLast)
        elif "<class 'dict'>" == str(type(value)) :
            debugLogJsonType_WriteTab(file, tabCount-1)
            file.write('"%s": ' % (key) )
            debugLogJsonType_IfDict(file, value, tabCount, checkLast)
        else :
            debugLogJsonType_WriteTab(file, tabCount-1)
            if False == checkLast :
                file.write('"%s": "%s",\n' % (key, value))
            else :
                file.write('"%s": "%s"\n' % (key, value))
        count = count + 1

    debugLogJsonType_WriteTab(file, tabCount-1)

    if False == checkLastRoot :
        file.write('},\n')
    else :
        file.write('}\n')


def debugLogJsonType_WriteTab(file, tabCount):
    count = 0
    while count < tabCount :
        file.write('\t')
        count = count + 1

 

사용법

    debugLogJsonType_EscapeSequenceOrigin('test_MyJson.log', './', subRuleResult)

 

결과

{
	"test": "/sbin/lsmod | /bin/grep hfsplus | /bin/awk \'{print} END {if (NR == 0) print \"pass\" ; else print \"fail\"}\'"
}

위와 같이 Escape Sequence 가 origin과 동일하게 저장됨.

 

주의

debugLogJsonType_EscapeSequenceOrigin 를 사용해서 json 형식으로 File write한 후 

다시 import json를 사용해서 아래 코드로 저장했던 json파일을 읽어오면

    with open(filePath, 'r', encoding='utf-8') as outFile:
        result = json.load(outFile)

위와 같이 

json.decoder.JSONDecodeError: Invalid \escape: line 2 column 54 (char 55)

오류가 발생함.

해당 오류 원인인 json file write 시 Escape Sequence 처리를 하고 저장하고

읽어올 시 다시 Escape Sequence 처리를 하고 읽어오는데 

json 패키지에서 읽어올 때 Escape Sequence 문제가 있다고 판단해서 오류가 발생함.

debugLogJsonType_EscapeSequenceOrigin 로 생성한 json 파일은

import json 으로 file read하진 못함.

반응형