Happily, the atoms used by the format are similar enough to Python that we can use the tokenize
and ast
modules for an ad-hoc parser.
It will probably break horribly on broken input, but works for your example data 🙂
import tokenize
import token
import ast
import io
import json
def parse_valve_format(data):
dest = {}
stack = [dest]
for tok in tokenize.tokenize(io.BytesIO(data.encode()).readline):
if tok.type == token.STRING:
ts = ast.literal_eval(tok.string)
if isinstance(stack[-1], str):
# already a string on the stack?
# this has to be a key-value setting
key = stack.pop(-1)
stack[-1][key] = ts
else:
# otherwise assume we'll find a } soon
stack.append(ts)
elif tok.type == token.OP and tok.string == "{":
obj = {}
key = stack.pop(-1)
stack[-1][key] = obj
stack.append(obj)
elif tok.type == token.OP and tok.string == "}":
assert isinstance(stack[-1], dict), "stray }"
stack.pop(-1)
return dest
result_dict = parse_valve_format(
"""
"items"
{
"first"
{
"a" "1"
"b" "2"
"c" "3"
"d" "4"
"e" "5"
}
"second"
{
"f" "6"
"g" "7"
"h" "8"
"i" "9"
"j" "10"
}
}
"""
)
print(json.dumps(result_dict, indent=2))
output:
{
"items": {
"first": {
"a": "1",
"b": "2",
"c": "3",
"d": "4",
"e": "5"
},
"second": {
"f": "6",
"g": "7",
"h": "8",
"i": "9",
"j": "10"
}
}
}
solved Convert Valve data structure to JSON [closed]