forked from langchain-ai/langchainjs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson.ts
85 lines (77 loc) · 2.24 KB
/
json.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
export function parseJsonMarkdown(s: string, parser = parsePartialJson) {
// eslint-disable-next-line no-param-reassign
s = s.trim();
const match = /```(json)?(.*)```/s.exec(s);
if (!match) {
return parser(s);
} else {
return parser(match[2]);
}
}
// Adapted from https://github.com/KillianLucas/open-interpreter/blob/main/interpreter/core/llm/utils/parse_partial_json.py
// MIT License
export function parsePartialJson(s: string) {
// If the input is undefined, return null to indicate failure.
if (typeof s === "undefined") {
return null;
}
// Attempt to parse the string as-is.
try {
return JSON.parse(s);
} catch (error) {
// Pass
}
// Initialize variables.
let new_s = "";
const stack = [];
let isInsideString = false;
let escaped = false;
// Process each character in the string one at a time.
for (let char of s) {
if (isInsideString) {
if (char === '"' && !escaped) {
isInsideString = false;
} else if (char === "\n" && !escaped) {
char = "\\n"; // Replace the newline character with the escape sequence.
} else if (char === "\\") {
escaped = !escaped;
} else {
escaped = false;
}
} else {
if (char === '"') {
isInsideString = true;
escaped = false;
} else if (char === "{") {
stack.push("}");
} else if (char === "[") {
stack.push("]");
} else if (char === "}" || char === "]") {
if (stack && stack[stack.length - 1] === char) {
stack.pop();
} else {
// Mismatched closing character; the input is malformed.
return null;
}
}
}
// Append the processed character to the new string.
new_s += char;
}
// If we're still inside a string at the end of processing,
// we need to close the string.
if (isInsideString) {
new_s += '"';
}
// Close any remaining open structures in the reverse order that they were opened.
for (let i = stack.length - 1; i >= 0; i -= 1) {
new_s += stack[i];
}
// Attempt to parse the modified string as JSON.
try {
return JSON.parse(new_s);
} catch (error) {
// If we still can't parse the string as JSON, return null to indicate failure.
return null;
}
}