4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSONアンエスケープ by Python

Last updated at Posted at 2019-08-21

ニッチな内容だけど、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': 'こんにちは'}

以上。

4
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?