A JSON text must at least contain two octets
JsonRubyJson Problem Overview
I received this error, and I couldn't find any reasonable answer to this question, so I thought I'd write a summary of the problem.
If you run this snippet in irb:
JSON.parse( nil )
You'll see the following error:
TypeError: can't convert nil into String
I was kind of expecting the function to return nil
, and not a TypeError
. If you convert all input using to_s
, then you'll see the octet error:
JSON::ParserError: A JSON text must at least contain two octets!
That's just fine and well. If you don't know what an octet is, read this post for a summary and solution: https://stackoverflow.com/questions/7200554/what-is-json-octet-and-why-are-two-required
Solution
The variable you're passing in is an empty string. Don't attempt to use an empty string in the JSON.parse
method.
Question
So, now I know the cause of the error, what pattern should I use to handle this? I'm a bit loathe to monkey patch the JSON library to allow nil
values. Any suggestions would be greatly appreciated.
Json Solutions
Solution 1 - Json
parsed = json && json.length >= 2 ? JSON.parse(json) : nil
But really the library should be able to handle this case and return nil. Web browsers with built-in JSON support seem to work just like you expect after all.
Or to do it with a only slightly intrusive mini patch:
module JSON
def self.parse_nil(json)
JSON.parse(json) if json && json.length >= 2
end
end
parsed = JSON.parse_nil(json)
Solution 2 - Json
data.presence && JSON.parse(data)
JSON.parse(data.presence || '{}')
Solution 3 - Json
According to json.org
JSON is built on two structures:
-
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
-
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
So, minimum two octets(8 bits) required at the top level would be {}
or []
IMO, the best solution would be to make sure the argument to JSON.parse
is either an strigified object or a strigified array. :-)
Solution 4 - Json
hash = JSON.parse(json) rescue {}
array = JSON.parse(json) rescue []
string = JSON.parse(json) rescue ''