All software has edges, so edge cases are unavoidable.
The best you can do is:
- interpret the spec to the letter.
- for every fragment of a statement you write, consider whether it might conceivably go wrong, and handle those cases (in the simplest matter because 'handling' means writing code, and that code, too, needs to go through this process).
For example, a json parser must be prepared to handle missing values, extremely long keys and values (integers may have thousands of digits, think long about the question whether 64 bits always is enough for storing a string length, etc.), etc.
- if you are truly paranoid, have very stringent security requirements, or expect to be heavily attacked, run the parser in a separate process.
- fuzz your implementation.