arktype
arktype copied to clipboard
Custom error for parse.json morph
Would be great to have a custom error message pointing out the specific section of JSON that failed to parse.
This is based on this suggestion in Effect's Discord by user spaethnl:
I have some parse errors that result from JSON.parse that look like this: ... │ └─ Unexpected non-whitespace character after JSON at position 560 []: # FILEPATH: /NewIssue.md []: # BEGIN: ed8c6549bwf9
It would be helpful if the context were shown to make it easier to track down the syntax error. Could parseJson in Schema.ts be updated to call a function like below (by chatGPT)? I updated it inline on my node_modules to try it out and it improved my error message to: │ └─ Unexpected non-whitespace character after JSON at position 560 ... Concern"]][["Counter ... ^
Generate a context string for JSON syntax errors. /** Given a SyntaxError from JSON.parse and the original JSON string, this function generates a two-line string that shows the error position. @param error - The SyntaxError object thrown by JSON.parse @param jsonData - The original JSON string that caused the error @param contextLength - The number of characters to show before and after the error position. Default is 10. @returns A string showing the error context in the original JSON data. @example const data = '[[1][2]]'; try { JSON.parse(data) } catch (e: SyntaxError) { console.log('Error:', e.message) console.log(generateJsonErrorContext(e, data)) } // Output: // Error: Unexpected token a in JSON at position 4 // ...[[1][2]] // ... ^ **/ function generateJsonErrorContext(error: SyntaxError, jsonData: string, contextLength: number = 10): string { const match = /position (\d+)/.exec(error.message); if (!match) return 'Could not determine error position.' const position = parseInt(match[1], 10); const start = Math.max(0, position - contextLength); const end = Math.min(jsonData.length, position + contextLength); const context = jsonData.substring(start, end); const pointer = ' '.repeat(position - start) + '^'; return `...${context}\n...${pointer}\n`; }