RFC 4627: The application type / json Media for JavaScript Object Notation (JSON) has the following:
2. JSON Grammar A JSON text is a sequence of tokens. The set of tokens includes six structural characters, strings, numbers, and three literal names. A JSON text is a serialized object or array. JSON-text = object / array [...] 2.1. Values A JSON value MUST be an object, array, number, or string, or one of the following three literal names: false null true
If you call to_json on your six samples, we get the following:
>> objects = [ {}, [], 42, "", true, nil ] >> objects.map { |o| puts o.to_json } {} [] 42 "" true null
Thus, the first and second are valid JSON texts, while the last four are invalid JSON texts, even if they are valid JSON values.
JSON.parse wants it to call a JSON document:
Parse the JSON document source into a Ruby data structure and return it.
Perhaps the JSON document is a library term for RFC 4627 to invoke JSON text. If so, then raising the exception is a reasonable response to invalid input.
If you forcefully wrap and expand everything:
objects.each do |o| json = o.to_json begin json_text = '[' + json + ']' p JSON.parse(json_text)[0] rescue Exception => e puts "Error parsing #{json.inspect}: #{e}" end end
And as you noticed in your comment, using an array as a wrapper is better than an object if the caller wants to use the parameter :symbolize_names . Such a wrapper means that you will always feed JSON text to JSON.parse , and everything should be fine.