Need help with your JSON?
Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool
JSON Parse Errors in Different Programming Languages
JSON has become the universal language for data interchange, but each programming language handles JSON parsing errors differently. Understanding these differences is crucial when debugging JSON issues in various environments or when building cross-language systems.
This article explores how major programming languages detect, report, and handle JSON parsing errors, providing examples and best practices for each language.
JavaScript
As the language JSON was designed for, JavaScript provides native parsing but with relatively sparse error information.
Parsing Mechanism
- Uses the native
JSON.parse()
method - Throws
SyntaxError
on invalid JSON - Error message includes only character position, not line numbers
- No built-in mechanism to display the problematic part of JSON
Basic JavaScript Parsing:
try { const data = JSON.parse('{"name": "JavaScript", "version": 2023,}'); // Invalid - trailing comma } catch (error) { console.error('JSON parse error:', error.message); // Output: "JSON parse error: Unexpected token } in JSON at position 39" }
Enhanced Error Handling:
function parseWithContext(jsonString) { try { return { data: JSON.parse(jsonString), error: null }; } catch (error) { // Extract position from error message const posMatch = error.message.match(/at position (\d+)/); const position = posMatch ? parseInt(posMatch[1], 10) : -1; // Provide visual context for the error let errorContext = ''; if (position >= 0) { const start = Math.max(0, position - 20); const end = Math.min(jsonString.length, position + 20); const excerpt = jsonString.substring(start, end); // Calculate the position within our excerpt const pointerPos = position - start; errorContext = ` Context: ${excerpt.replace(/\n/g, ' ')} ${'~'.repeat(pointerPos)}^ Error occurs here `; } return { data: null, error: error.message, position: position, context: errorContext }; } } const result = parseWithContext('{"name": "JavaScript", "version": 2023,}'); if (result.error) { console.error(`Error: ${result.error}`); console.log(result.context); }
Common JavaScript JSON Errors
Error Message | Likely Cause |
---|---|
Unexpected token { in JSON | Invalid object start, often in an unexpected place |
Unexpected token : in JSON | Missing or invalid property name before a colon |
Unexpected end of JSON input | Incomplete JSON string, often missing closing brackets |
Unexpected token } in JSON | Unexpected closing brace, perhaps due to mismatched brackets |
Unexpected token ' in JSON | Single quotes instead of required double quotes |
Python
Python provides more detailed error information than JavaScript.
Parsing Mechanism
- Uses the
json
module in the standard library - Main function is
json.loads()
(for strings) orjson.load()
(for files) - Raises
json.JSONDecodeError
which includes line, column, and position - Error message indicates what character was expected
Python Example:
import json def parse_with_context(json_str): try: data = json.loads(json_str) return {'data': data, 'error': None} except json.JSONDecodeError as e: # Extract detailed error information error_info = { 'message': str(e), 'line': e.lineno, 'column': e.colno, 'position': e.pos } # Get the line with the error lines = json_str.split('\n') if 0 <= e.lineno - 1 < len(lines): error_line = lines[e.lineno - 1] pointer = ' ' * (e.colno - 1) + '^' # Include a few surrounding lines for context start_line = max(0, e.lineno - 3) end_line = min(len(lines), e.lineno + 2) context_lines = [] for i in range(start_line, end_line): prefix = '-> ' if i == e.lineno - 1 else ' ' context_lines.append(f"{prefix}{i+1}: {lines[i]}") # Add pointer line context_lines.insert(e.lineno - start_line + 1, ' ' + pointer) error_info['context'] = '\n'.join(context_lines) return {'data': None, 'error': error_info} # Example usage json_with_error = ''' { "name": "Python", "version": 3.11, "features": [ "type hints", "async/await", "pattern matching", ] } ''' # Invalid JSON - trailing comma in array result = parse_with_context(json_with_error) if result['error']: print(f"Error: {result['error']['message']}") print(result['error']['context']) # Output: # Error: Expecting value delimiter: line 7 column 6 (char 109) # 3: { # 4: "name": "Python", # 5: "version": 3.11, # 6: "features": [ # -> 7: "type hints", # ^ # 8: "async/await", # 9: "pattern matching",
Java
Java offers detailed error messages, especially with popular libraries like Jackson.
Parsing Mechanism
- Most commonly uses the Jackson library
- Key class is
ObjectMapper
with methods likereadValue()
- Throws
JsonParseException
with detailed location and character information - Exception includes full source location and expected token details
Java Example with Jackson:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonParseException; public class JsonErrorExample { public static void main(String[] args) { String jsonWithError = "{\"name\": \"Java\", \"version\": 17,}"; // Invalid JSON - trailing comma try { ObjectMapper mapper = new ObjectMapper(); Map<String, Object> data = mapper.readValue(jsonWithError, Map.class); System.out.println("Parsed successfully: " + data); } catch (JsonParseException e) { System.out.println("Parse error: " + e.getMessage()); // Output includes line/column and detailed error: // "Parse error: Unexpected character ('}' (code 125)): expected a value at [Source: (String)"{"name": "Java", "version": 17,}"; line: 1, column: 31]" // Print only the relevant part of the message String message = e.getMessage(); int atIndex = message.indexOf(" at ["); if (atIndex > 0) { System.out.println("Error: " + message.substring(0, atIndex)); System.out.println("Location: " + message.substring(atIndex)); } // Parse location information int line = e.getLocation().getLineNr(); int column = e.getLocation().getColumnNr(); // Extract source and provide visual context String source = jsonWithError; if (source != null) { String[] lines = source.split("\n"); if (lines.length > 0 && line <= lines.length) { String errorLine = lines[line - 1]; StringBuilder pointer = new StringBuilder(); for (int i = 0; i < column - 1; i++) { pointer.append(" "); } pointer.append("^"); System.out.println("Context:"); System.out.println(errorLine); System.out.println(pointer.toString()); } } } catch (Exception e) { System.out.println("Other error: " + e.getMessage()); } } }
C# (.NET)
C# provides rich error information and configuration options.
Parsing Mechanism
- Modern .NET uses
System.Text.Json
namespace - Key method is
JsonSerializer.Deserialize()
- Throws
JsonException
with path, line, byte position, and message - Offers configuration options to control parsing behavior
C# Example:
using System; using System.Text.Json; using System.Text.Json.Serialization; public class JsonErrorDemo { public static void Main() { string jsonWithError = @"{ ""name"": ""C#"", ""version"": 10, ""features"": [""Records"", ""Pattern matching"",] // Invalid - trailing comma }"; try { var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, AllowTrailingCommas = false // For demonstration, default is false }; var data = JsonSerializer.Deserialize<dynamic>(jsonWithError, options); Console.WriteLine("Successfully parsed"); } catch (JsonException e) { Console.WriteLine($"JSON Error: {e.Message}"); // Output includes line, position, and path: // "JSON Error: ',' is an invalid start of a value. Path: $.features[1] | LineNumber: 4 | BytePositionInLine: 44." // Extract line and position info int lineNumber = 0; int position = 0; string path = ""; // Parse error details from message var lineMatch = System.Text.RegularExpressions.Regex.Match(e.Message, @"LineNumber: (d+)"); if (lineMatch.Success) lineNumber = int.Parse(lineMatch.Groups[1].Value); var posMatch = System.Text.RegularExpressions.Regex.Match(e.Message, @"BytePositionInLine: (d+)"); if (posMatch.Success) position = int.Parse(posMatch.Groups[1].Value); var pathMatch = System.Text.RegularExpressions.Regex.Match(e.Message, @"Path: ([^|]+)"); if (pathMatch.Success) path = pathMatch.Groups[1].Value.Trim(); Console.WriteLine($"Error at line {lineNumber}, position {position}, path {path}"); // Display the problematic line string[] lines = jsonWithError.Split(' '); if (lineNumber > 0 && lineNumber <= lines.Length) { string errorLine = lines[lineNumber - 1]; Console.WriteLine("\nContext:"); Console.WriteLine(errorLine); // Create pointer to error position string pointer = new string(' ', position) + "^"; Console.WriteLine(pointer); } } } }
C# Feature Note:
Unlike most other languages, System.Text.Json in .NET offers the AllowTrailingCommas
option, which can be set to true
to make the parser more lenient about trailing commas in objects and arrays.
PHP
PHP offers simple but effective JSON parsing with function-based error handling.
Parsing Mechanism
- Uses
json_decode()
function for parsing - Returns
null
on parsing failure rather than throwing exceptions - Error details can be retrieved with
json_last_error()
andjson_last_error_msg()
- Error messages tend to be less descriptive than other languages
PHP Example:
<?php // Basic error handling in PHP $jsonString = '{"name": "Michael", "age": 42,}'; // Invalid JSON - trailing comma $data = json_decode($jsonString); if ($data === null && json_last_error() !== JSON_ERROR_NONE) { echo "Error: " . json_last_error_msg() . "\n"; // Output: "Error: Syntax error" } // Enhanced error handling with context function parseJsonWithContext($jsonString) { $result = json_decode($jsonString); if ($result !== null || json_last_error() === JSON_ERROR_NONE) { return ['data' => $result, 'error' => null]; } $error = json_last_error_msg(); // PHP's error messages don't include position information // Let's do some heuristic-based context extraction // For trailing commas, look for patterns like ",}" if (preg_match('/,\s*[\}\]]/', $jsonString, $matches, PREG_OFFSET_CAPTURE)) { $pos = $matches[0][1]; $excerpt = substr($jsonString, max(0, $pos - 20), 40); $error .= "\nPossible trailing comma near: " . $excerpt; } // For unquoted keys or values if (preg_match('/[{,]\s*([^"\s][^:]*):/', $jsonString, $matches)) { $error .= "\nPossible unquoted property name: " . $matches[1]; } return ['data' => null, 'error' => $error]; } $result = parseJsonWithContext($jsonString); if ($result['error']) { echo $result['error'] . "\n"; } ?>
Common PHP JSON Errors
Error Constant | Message | Common Cause |
---|---|---|
JSON_ERROR_SYNTAX | Syntax error | Most syntax errors (unhelpfully generic) |
JSON_ERROR_UTF8 | Malformed UTF-8 characters | Encoding issues or invalid characters |
JSON_ERROR_DEPTH | Maximum stack depth exceeded | Nested structures exceeding limits |
Ruby
Ruby offers concise but informative JSON parsing errors.
Parsing Mechanism
- Uses the
json
gem (part of standard library since Ruby 1.9) - Parsing is done with
JSON.parse()
- Raises
JSON::ParserError
with line, column, and token information - Error messages are concise but helpful
Ruby Example:
require 'json' # Basic error handling begin data = JSON.parse('{"name": "Ruby", "version": 3.1,}') # Invalid JSON - trailing comma rescue JSON::ParserError => e puts "Error: #{e.message}" # Output: "Error: unexpected token at '{"name": "Ruby", "version": 3.1,}'" end # Enhanced error visualization def parse_with_context(json_str) begin JSON.parse(json_str) rescue JSON::ParserError => e # Extract error location from message if available # Ruby's error messages don't always include position details pos_match = e.message.match(/at '(.*)'$/) error_context = pos_match ? pos_match[1] : "" puts "JSON Parse Error: #{e.message}" # Try to identify the problematic location if json_str.include?(error_context) position = json_str.index(error_context) before = json_str[0...position].split("\n") line_num = before.length column = before.empty? ? 0 : before.last.length puts "Approximate location: Line #{line_num}, Column #{column}" # Show a few lines of context lines = json_str.split("\n") start_line = [0, line_num - 3].max end_line = [lines.length - 1, line_num + 2].min puts "\nContext:" (start_line..end_line).each do |i| line_marker = i + 1 == line_num ? ">" : " " puts "#{line_marker} #{i + 1}: #{lines[i]}" end end return nil end end parse_with_context('{"name": "Ruby", "version": 3.1,}')
Go
Go provides detailed error information with a focus on simplicity.
Parsing Mechanism
- Uses the standard library's
encoding/json
package - Primary method is
json.Unmarshal()
- Returns errors with detailed messages including line/column information
- Error types include
*json.SyntaxError
and*json.UnmarshalTypeError
Go Example:
package main import ( "encoding/json" "fmt" ) func main() { jsonString := `{ "name": "Go", "version": 1.18, }` // Invalid JSON - trailing comma var data map[string]interface{} err := json.Unmarshal([]byte(jsonString), &data) if err != nil { fmt.Printf("Error: %v\n", err) // Check for specific error types if syntaxErr, ok := err.(*json.SyntaxError); ok { // Get the approximate line/column line, col := findLineCol(jsonString, int(syntaxErr.Offset)) fmt.Printf("Syntax error at line %d, column %d\n", line, col) // Print the problematic line printErrorContext(jsonString, line) } } else { fmt.Println("Parsed successfully:", data) } } // Helper to find line and column from byte offset func findLineCol(input string, offset int) (line, col int) { line = 1 col = 1 for i := 0; i < offset && i < len(input); i++ { if input[i] == '\n' { line++ col = 1 } else { col++ } } return line, col } // Helper to print the context of the error func printErrorContext(input string, errorLine int) { lines := strings.Split(input, "\n") if errorLine > 0 && errorLine <= len(lines) { startLine := max(0, errorLine-2) endLine := min(len(lines), errorLine+2) fmt.Println("Error context:") for i := startLine; i < endLine; i++ { prefix := " " if i+1 == errorLine { prefix = "> " } fmt.Printf("%s%d: %s\n", prefix, i+1, lines[i]) } } }
Cross-Language Comparison
Error Information Richness
Language | Position Info | Error Detail | Context Info |
---|---|---|---|
JavaScript | Character position only | Minimal | None |
Python | Line, column, position | Good | None, but error class is specific |
Java (Jackson) | Line, column, position | Excellent | Detailed token expectations |
C# (.NET) | Line, position, path | Excellent | JSON path to error |
PHP | None | Poor | Error constant only |
Ruby | Partial (in message) | Moderate | Problematic token |
Go | Byte offset | Good | Specific error types |
Common Error Patterns Across Languages
- Similar error detection - Most languages catch the same core syntax errors
- Position reporting variation - Some give character-level precision, others only line numbers
- Error message clarity - Ranges from cryptic (PHP) to very descriptive (Java/C#)
- Context provision - Most require custom code to show the problematic JSON context
Best Practices for Cross-Language JSON
1. Validate Before Sending
Always validate JSON before transmitting it to other systems, especially if those systems use different programming languages:
- Use a JSON validator in your primary language
- Consider a schema validation system like JSON Schema
- Add integration tests that verify JSON compatibility
2. Enhance Error Reporting
Implement better error handling in your application:
- Create wrapper functions that provide consistent, detailed error messages
- Include visual context (the problematic line, pointer to error position)
- For languages with poor position reporting (like PHP), implement heuristics to locate errors
3. Use Language-Appropriate Features
Take advantage of language-specific features:
- JavaScript: Consider libraries like
json5
orjju
for more detailed errors - Python: Use the
JSONDecodeError
exception directly for detailed position information - Java: Choose Jackson for better error reporting than alternatives
- C#: Enable appropriate
JsonSerializerOptions
based on your needs
4. Standardize Error Handling Code
Create reusable error handling patterns to use across your projects:
- Create utility functions for parsing with enhanced error reporting
- Implement language-specific wrappers with consistent error formats
- Consider building or using middleware for web APIs that standardizes JSON error handling
Conclusion
Understanding how different programming languages handle JSON parsing errors is essential when debugging cross-platform applications or building systems that communicate via JSON.
Each language has its own approach to error reporting, from JavaScript's minimal position information to C#'s and Java's detailed error context. By enhancing the default error handling with custom visualizations and context information, you can create a more consistent debugging experience regardless of the language you're working with.
Remember that prevention is better than debugging — validate JSON at creation time, use schema validation where appropriate, and implement thorough testing to catch JSON issues before they reach production.
Need help with your JSON?
Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool