# JSON Implementation in mq
def _parse_json_value(input):
let input = trim(input)
|
def handle_string_char(char, escaped, pos):
if (char == "\"" && !escaped):
[true, pos]
elif (char == "\""):
[false, !escaped]
else:
[false, false]
end
def _parse_string(input):
let escaped = false
| let pos = 1
| let end_pos = None
| let input_len = len(input)
| let pos = while (is_none(end_pos) && pos < input_len):
let char = input[pos]
| let tokens = handle_string_char(char, escaped, pos)
| let should_end = tokens[0]
| let new_escaped = tokens[1]
| let end_pos = if (should_end): pos else: None
| let escaped = if (!should_end): new_escaped else: false
| let pos = pos + 1
| pos
end
| let str_content = input[1:pos - 1]
| let remaining = input[pos:len(input)]
| [str_content, remaining]
end
def _parse_number(input):
let input = trim(input)
| let number_pattern = "^(-?[0-9]+(?:\\.[0-9]+)?)"
| let match_result = regex_match(input, number_pattern)
| if (is_empty(match_result)):
[None, input]
else:
do
let number_str = first(match_result)
| let remaining = input[len(number_str):len(input)]
| [to_number(number_str), remaining]
end
end
def _parse_boolean(input):
let input = trim(input)
| if (starts_with(input, "true")):
[true, input[4:len(input)]]
elif (starts_with(input, "false")):
[false, input[5:len(input)]]
else:
[None, input]
end
def _parse_null(input):
let input = trim(input)
| if (starts_with(input, "null")):
[None, input[4:len(input)]]
else:
[None, input]
end
def _parse_array_value(input):
let input = input[1:len(input)]
| let input = trim(input)
| let elements = []
| let finish = false
| if (starts_with(input, "]")):
[elements, input[1:len(input)]]
else:
while (!finish):
let tokens = _parse_json_value(input)
| let value = tokens[0]
| let rest = tokens[1]
| let elements = elements + [value]
| let input = trim(rest)
| if (is_none(value)): error("Invalid JSON array element")
| let finish = starts_with(input, "]")
| let input = if (starts_with(input, ",")):
trim(input[1:len(input)])
elif (starts_with(input, "]")):
trim(input[1:len(input)])
else:
error("Expected ',' or ']' in array")
| [elements, input];
end
def _parse_array(input):
let input = trim(input)
| if (not(starts_with(input, "["))):
[None, input]
else:
_parse_array_value(input)
end
def _parse_object_value(obj, key, input):
let input = trim(input[1:len(input)])
| let tokens = _parse_json_value(input)
| let value = tokens[0]
| let rest = tokens[1]
| let obj = set(obj, key, value)
| let input = trim(rest)
| if (starts_with(input, ",")):
[obj, trim(input[1:len(input)])]
elif (starts_with(input, "}")):
[obj, input]
elif (is_empty(input)):
[obj, trim(input)]
else:
error("Expected ',' or '}' in object")
end
def _parse_object(input):
let input = input[1:len(input)]
| let input = trim(input)
| let obj = {}
| let result = if (starts_with(input, "}")):
[obj, input[1:len(input)]]
else:
while (!starts_with(input, "}") && !is_empty(input)):
let tokens = _parse_string(input)
| let key = tokens[0]
| let input = trim(tokens[1])
| if (is_none(key)): error("Invalid JSON object key")
| if (!starts_with(input, ":")): error("Expected ':' after object key")
| let result = _parse_object_value(obj, key, input)
| let obj = result[0]
| let input = trim(result[1])
| let result = if (starts_with(input, ",")):
[obj, input[1:len(input)]]
else:
[obj, input]
| let obj = result[0]
| let input = trim(result[1])
| [obj, input]
end
| let obj = result[0]
| let input = result[1]
| if (starts_with(input, "}")):
[obj, trim(input[1:len(input)])]
else:
[obj, input]
end
def parse_object(input):
let input = trim(input)
| if (!starts_with(input, "{")):
[None, input]
else:
_parse_object(input)
end
| if (starts_with(input, "{")):
_parse_object(input)
elif (starts_with(input, "[")):
_parse_array(input)
elif (starts_with(input, "\"")):
_parse_string(input)
elif (starts_with(input, "t") || starts_with(input, "f")):
_parse_boolean(input)
elif (starts_with(input, "n")):
_parse_null(input)
else:
_parse_number(input)
end
# Parses a JSON string and returns the corresponding data structure.
def json_parse(input):
let data = _parse_json_value(to_string(input))
| data[0]
end
# Serializes a value to a JSON string.
def json_stringify(data):
def _format_json_stringify(data):
"\"" + data + "\""
end
def _json_array_stringify(data):
"[" + join(map(data, json_stringify), ", ") + "]"
end
def _json_object_stringify(data):
"{" + join(
map(entries(data),
fn(entry): "\"" + first(entry) + "\": " + json_stringify(last(entry));), ", ") + "}"
end
| if (is_string(data)):
_format_json_stringify(data)
elif (is_number(data)):
to_string(data)
elif (is_bool(data)):
to_string(data)
elif (is_none(data)):
"null"
elif (is_array(data)):
_json_array_stringify(data)
elif (is_dict(data)):
_json_object_stringify(data)
else:
to_string(data)
end
# Converts a JSON data structure to a Markdown table.
def json_to_markdown_table(data):
def _create_array_markdown_table(data):
let headers = keys(first(data))
| let header_row = "| " + join(headers, " | ") + " |"
| let separator_row = "| " + join(map(headers, fn(_): "---";), " | ") + " |"
| let data_rows = map(data, fn(row):
"| " + join(map(headers, fn(header): if (is_none(row[header])): "" else: replace(to_string(row[header]), "\n", "\\n");), " | ") + " |"
end)
| [header_row, separator_row] + data_rows
| join("\n")
end
def _create_dict_markdown_table(data):
let headers = ["Key", "Value"]
| let header_row = "| " + join(headers, " | ") + " |"
| let separator_row = "| " + join(map(headers, fn(_): "---";), " | ") + " |"
| let data_rows = map(keys(data), fn(key):
"| " + key + " | " + (if (is_none(data[key])): "" else: replace(to_string(data[key]), "\n", "\\n")) + " |"
end)
| [header_row, separator_row] + data_rows
| join("\n")
end
def _create_simple_markdown_table(data):
"| Value |\n| --- |\n| " + to_string(data) + " |"
end
| if (is_array(data)):
_create_array_markdown_table(data)
elif (is_dict(data)):
_create_dict_markdown_table(data)
else:
_create_simple_markdown_table(data)
end