ニッチな内容だけど、JSONのvalueの中の入れ子なJSON形式を、「"」をアンエスケープさせつつ文字列として格納する方法のメモ。
jsonパッケージを使う。
import json
まず、入れ子構造になったJSON形式を、jsonパッケージで文字列にdumpすると下記の通り。
dict1 = {
"key1" : {
"key2" : {
"key3" : "value"
}
}
}
s = json.dumps(dict1)
s
# 出力結果
# '{"key1": {"key2": {"key3": "value"}}}'
という感じで、入れ子要素もすべて「"キー" : "値"」というフラットな構造の文字列となる。
これに対し、入れ子要素を文字列として保存し、さらにその入れ子も文字列として、、と保存する。
やり方は、単純に、段階的にjson.dumpsを呼べば良い。
dict1["key1"]["key2"] = json.dumps(dict1["key1"]["key2"]) #文字列 '{"key3": "value"}'
dict1['key1'] = json.dumps(dict1["key1"]) #文字列 '{"key2": "{\\"key3\\": \\"value\\"}"}'
s = json.dumps(dict1)
s
# 出力結果
'{"key1": "{\\"key2\\": \\"{\\\\\\"key3\\\\\\": \\\\\\"value\\\\\\"}\\"}"}'
という感じでJSON文字列の入れ子を作れる。
なお、json.dumpsは「"」をアンエスケープしてくれる仕様のため、入れ子の深さの数だけ「"」がアンエスケープした形で保持される。
復号には、同じ回数のjson.loadsを呼べば良い。
key1_d = json.loads(s)
key1_d
# 出力結果
{'key1': '{"key2": "{\\"key3\\": \\"value\\"}"}'}
key2_d = json.loads(key1_d["key1"])
key2_d
# 出力結果
{'key2': '{"key3": "value"}'}
key3_d = json.loads(key2_d["key2"])
key3_d
# 出力結果
{'key3': 'value'}
呼び出しのたびにエスケープされつつ、文字列が復元されるのがわかる。
ちなみに、文字列に日本語(UTF8)が含まれる場合、json.dumpsは、バイト列に変換するためアンエスケープがさらに激しいことになるが、驚かないようにされたい。
dict1 = {
"key1" : {
"key2" : {
"key3" : "こんにちは"
}
}
}
dict1["key1"]["key2"] = json.dumps(dict1["key1"]["key2"])
dict1['key1'] = json.dumps(dict1["key1"])
s = json.dumps(dict1)
s
# 出力結果
'{"key1": "{\\"key2\\": \\"{\\\\\\"key3\\\\\\": \\\\\\"\\\\\\\\u3053\\\\\\\\u3093\\\\\\\\u306b\\\\\\\\u3061\\\\\\\\u306f\\\\\\"}\\"}"}'
と、なかなか読み難いものになる。
同様に復号も可能。
key1_d = json.loads(s)
key1_d
# 出力結果
{'key1': '{"key2": "{\\"key3\\": \\"\\\\u3053\\\\u3093\\\\u306b\\\\u3061\\\\u306f\\"}"}'}
key2_d = json.loads(key1_d["key1"])
key2_d
# 出力結果
{'key2': '{"key3": "\\u3053\\u3093\\u306b\\u3061\\u306f"}'}
key3_d = json.loads(key2_d["key2"])
key3_d
# 出力結果
{'key3': 'こんにちは'}
以上。